악기를 다루지 못하는 개발자가 "왜 하필 그 음들인가"에 대한 설명 없이 암기만 시키는 음악 교육에 답답함을 느껴, Web Audio API와 JavaScript로 물리와 산수에서부터 음악 이론을 직접 유도해본 글
시간에 따라 변하는 숫자 하나에서 출발해 12음, 음계, 화음을 배열로 만들고, 실제 음악처럼 들리는 코드 진행까지 도달함. 모든 예제는 의존성 없는 순수 JS이고 글 안에서 직접 실행해 들어볼 수 있음
소리는 시간에 따라 변하는 숫자임
소리는 공기 압력의 떨림이고, 디지털 오디오는 초당 44,000번 스피커 콘의 위치를 지정하는 숫자 목록임
440Hz 사인파에서 음악적 의미를 갖는 숫자는 440뿐인데, 그마저도 누군가 "라(A)"라고 부르기로 합의한 임의의 기준음임
음이 끝날 때 "딸깍" 소리가 나는 것은 파형 중간에 진동이 끊겨 압력이 순간적으로 점프하기 때문이며, 음량 곡선(엔벨로프)으로 해결함 — 어택(소리가 커지는 구간)만 길게 늘여도 주파수 변화 없이 "뜯는 소리"가 "활로 켜는 소리"로 바뀜
음색의 정체는 함께 울리는 배음들임
440Hz로 조율된 기타 줄은 절반·1/3·1/4 길이 단위로도 동시에 진동하며 880, 1320, 1760Hz를 함께 냄 — 이것이 배음렬임
각 배음이 얼마나 크게 섞이는지의 배합비가 바이올린과 트럼펫을 가르는 음색이며, 사각파는 홀수 배음만 있어 속이 빈 전자음처럼, 톱니파는 배음을 전부 담아 거칠게 들림
주파수를 2배로 하면 같은 음이 됨
110, 220, 440, 880Hz는 높이가 다른데도 "같은 음"으로 들리며, 서로 교류가 없던 문화권들도 독립적으로 같은 결론(옥타브)에 도달함
이유: 440Hz가 내는 모든 배음은 이미 220Hz의 배음렬에 전부 포함되어 있음. 즉 한 옥타브 위 음은 새로운 소리 성분을 하나도 추가하지 않으므로, 귀에는 다른 음이 아니라 같은 음이 더 밝게 울리는 것으로 들림
여기서 두 가지가 따라 나옴 — 음정은 덧셈이 아니라 곱셈(모든 음정은 비율)이고, 옥타브 하나만 어떻게 나눌지 정하면 나머지 전체 음역은 자동으로 해결됨
단순한 정수비가 좋게 들리는 이유
2/1(옥타브), 3/2(완전5도), 4/3(완전4도), 5/4(장3도)는 화음처럼 들리고, 16/15(반음)는 서로 부딪히는 소리, √2는 사이렌처럼 거슬리는 소리가 남 — 분수가 단순할수록 듣기 좋음
이유 1: 3:2 관계의 두 음은 배음이 정확히 겹쳐 서로를 보강함. √2 비율은 어느 배음도 일치하지 않음
이유 2: 주파수가 살짝 다른 두 음은 음량이 주기적으로 울렁이는 맥놀이를 일으키며, 복잡한 분수일수록 몇 Hz 차이 나는 배음 쌍이 널려 있어 전부 맥놀이를 냄 — 이것이 불협화음의 정체임
결론: 협화음이란 두 파형을 합친 모양이 짧은 주기로 반복되어 귀가 그 패턴을 금방 알아채는 것임
완전5도 쌓기, 그리고 고칠 수 없는 버그
옥타브 다음으로 깨끗한 비율인 3/2를 12번 쌓아 올리면(피타고라스 조율) 출발음 220Hz가 아니라 222.99Hz에 도착함 — 이 구조적 오차가 "피타고라스 콤마"(약 23센트, 피아노 인접 건반 간격의 1/4쯤)임
프로그래머라면 바로 알아볼 이유로 수정 불가능함: 5도 쌓기는 3^n/2^n, 옥타브는 2^m이라 둘이 만나려면 3의 거듭제곱 = 2의 거듭제곱이어야 하는데, 둘 다 소수라 영원히 성립하지 않음
역사상 모든 조율법은 이 오차를 어디에 배분할지에 대한 서로 다른 선택임
평균율이라는 타협
현대의 답: 순정한 비율을 전부 포기하고 옥타브를 12개의 균등한 곱셈 단계(2의 12제곱근)로 나눔 — 옥타브만 정확하고 나머지는 전부 근사치가 됨
왜 하필 12등분인지는 15줄짜리 브루트포스 코드로 확인 가능함: 12는 완전5도를 약 0.1% 오차로 근사할 수 있는 최소의 분할 수이며, 이보다 나은 결과는 29등분, 41등분에나 가서야 나옴 — 건반 수 대비 효율이 가장 좋은 선택임
평균율의 5도는 순정 5도보다 2센트 낮고, 이 미세한 맥놀이는 지구상 모든 피아노의 모든 5도에 존재함 — "한 조(key)에서만 완벽한 것보다 모든 조에서 조금씩 틀린 게 낫다"는 합의임
보상: 음이 정수가 됨(MIDI 번호, 가온 다(C)=60). 이후의 모든 것은 주파수가 아닌 정수 배열로 처리됨
12음이 있다고 12음을 다 쓰지는 않음
12음을 순서대로 다 연주하면 모든 간격이 똑같아 어떤 음도 두드러지지 않고, 곡의 중심이 되는 음도 생기지 않아 멜로디가 아니라 효과음처럼 들림
음악은 간격이 불균등해지도록 고른 부분집합(음계)을 씀 — 간격이 불균등해야 지금 어느 음에 있는지 귀로 구분할 수 있음. 장음계는 온음·반음 간격을 나열한 [2,2,1,2,2,2,1]이라는 7원소 배열이고, 숫자 몇 개만 바꾸면 단음계, 펜타토닉, 블루스 스케일이 됨
그리스 이름 7개를 외우게 하던 선법(mode)은 알고 보면 같은 배열의 회전임 — 장음계(Ionian)는 회전 0, 자연 단음계(Aeolian)는 회전 5로, "장조와 단조는 별개의 체계가 아니라 같은 배열의 다른 회전"임
화음은 3도 간격으로 쌓은 음들임
음계에서 한 칸씩 건너뛰어 음을 집으면([0,2,4] 인덱싱) 3화음이 나옴 — 다장조의 으뜸화음(도-미-솔)은 반음 수로 [0,4,7], 주파수비로 거의 4:5:6이라 배음이 곳곳에서 겹침
장3화음 [0,4,7]과 단3화음 [0,3,7]의 차이는 가운데 원소 하나가 반음 낮은 것뿐임 — 서양 음악의 "밝음/슬픔"이라는 양대 정서가 배열 원소 하나 차이라는 것
한 음계의 각 음도 위에 3화음을 쌓으면 장3화음 3개, 단3화음 3개, 감3화음 1개가 자동으로 나옴 — 누가 정한 게 아니라 음계의 불균등한 간격이 강제한 결과임
로마 숫자 표기(I ii iii IV V vi vii°)는 화음을 이름이 아니라 음계 내 위치로 가리키는 상대 주소 지정임 — 로마 숫자 코드 차트는 조에 독립적인 소스 코드이고, 조옮김은 상수를 더하는 연산일 뿐임
긴장과 해소
전체 시스템에서 가장 강한 당김은 딸림화음(V) → 으뜸화음(I)이며, 이유가 구체적임: V에 포함된 "시"는 으뜸음 "도"의 반음 아래에 있는 이끎음이라 다음 음으로 올라가려는 강한 방향성을 만들고, 딸림7화음 속의 시–파는 정확히 반 옥타브(트라이톤 = √2, 앞서 가장 거슬리게 들리던 바로 그 무리수 비율)로 가장 불안정한 음정임
I로 갈 때 이 두 음이 반음씩 서로 반대 방향으로 움직이며 해소됨 — "긴장이 풀린다"는 느낌의 실체는 무리수 비율이 단순한 정수비로 교체되는 구체적인 사건임
I-V-vi-IV(팝의 상당수), ii-V-I(재즈의 근간) 같은 진행을 배열로 시연함. 같은 7음으로 만든 화음들이라 1~7의 거의 어떤 수열도 그럭저럭 어울리며, 1로 끝나면 곡이 끝난 느낌, 5로 끝나면 다음 소절이 이어질 것 같은 느낌이 남
악보는 직렬화 포맷임
오선보는 인쇄가 비싸던 시절에 설계되어, 연주로 손이 바쁜 인간이 실시간으로 읽도록 최적화되고, 이미 쓰는 사람이 너무 많아 한 번도 개정되지 못한 직렬화 포맷임
세로축은 12반음이 아니라 음계의 계단(온음계 축)이라, 가장 흔히 쓰는 장음계가 오선지 위에서 단순한 일직선으로 보이도록 최적화되어 있음
조표는 DRY 원칙임 — 라장조 곡에서 모든 파·도에 #을 일일이 붙이는 대신 각 줄 맨 앞에 상수로 한 번만 선언함. "이 곡은 라장조"라는 정보가 본문이 아닌 헤더에 있는 셈임
음길이는 2의 거듭제곱(온음표→2분→4분→8분음표)으로 2진 지수를 시각적으로 인코딩한 것이며, 점음표의 점은 1.5배 연산자임. 음표는 절대 시간이 아닌 박(beat)을 저장하고 템포(BPM)를 정해야 초 단위가 되므로, 악보에는 상대 길이만 있고 실제 시계는 연주자가 공급함
종합
12음은 소수 2와 3이 만드는 오차를 절충한 결과, 음계는 귀로 길을 찾을 수 있게 간격을 불균등하게 고른 부분집합, 화음은 배음이 이미 겹치는 음들의 조합, 조성은 상대 주소 지정, 악보는 헤더가 있는 직렬화 포맷 — 전부 오래전 제약 속에서 내려진 평범한 엔지니어링 결정이며, 파고들면 그 이유가 지금도 남아 있음
리듬, 성부 진행(voice leading), 선율이 왜 특정 음으로 향하는지는 아직 이해하지 못한 영역으로 남겨둠. 참고 자료로 Eevee의 "Music Theory for Nerds"와 LightNote를 추천함