Yamaha OPL/N/M/X..

일년 중에 잉여력이 돋는 시절이 아닌데, 재미삼아 이 세계를 들여다보니 의외로 재미있는 구석이 많겠다 싶어서 이것 저것 계속 찾아보고 있다.

mame rom에서 음악 데이터만 찾아내서 그것을 wave로 만들어주는 앱도 나온지가 한참인데다 이미 mame에서는 yamaha synth chip을 얼마전에 총정리를 한 모양이다.

어쨌든 특성만 뽑아서 보면

또 하나는 YM시리즈 말고도 OKI6295라는 칩이 옛날에 인기를 끌었던 모양인데, 내부 블록을 보면 사실 4bit ADPCM만 play하는 기능 뿐이라고 우습게 볼 수도 있지만 사실 게임기 (콘솔)에서 사람 음성이라든가 또는 뭔가 제대로 된 드럼 소리가 나는 진화가 1990년이 다 되서 (87년에 나왔다고 한다) 이루어진 일이고 여기에 이 칩이 일조를 했다고 한다. 물론 이후 동일 기능 혹은 더 향상된 기능이 들어간 모듈이 모두 통합이 되긴 했지만 말이다.

잘은 모르지만 지금은 ADPCM같은 것은 학교에서 예제로 가르치지도 않을 것 같은 옛날 토픽이지 싶다. 그런 걸 생각하면 앞으로는 어떤 것의 본질을 거의 모른 채로 그냥 deep learning을 하는 플랫폼에 데이터를 쏟아붓기만 하겠구나 하는 생각도 아울러 든다. 어차피 컴퓨터는 넘쳐나고 저장공간도 넘쳐나니 뭐는 못하겠냐만. 그 옛날엔 1비트라도 더 아껴서 싸게만들려고 아주 애를 썼구나 싶다.

본론으로 돌아와서 여기서는 어떤 체계로 음을 합성하는지 간단하게 정리하면

waveform generation

기종 별로 차이가 있긴 하지만 아래의 그림으로 총정리가 된다.

waveforms

대개 1-4번 waveform은 지원한다고 보면 될 것 같다.

그림에서 보는 것과 같이 일단 이 wave pattern을 기본으로 여기에 phase term을 특정 패턴에 따라 가변하여 기본적인 음을 생성하게 된다.

operators

이것은 야마하의 사람들이 붙인 이름인 것 같은데 여하간 이 체계 안에서 음을 합성하기 위한 최소의 단위로 보면 될 것 같다. 이것은 다음으로 구성된다.

0) external phase input 1) phase generator 2) sine table 3) envelope generator

그러니까 매 clock 더 해지는 phase의 값 (=frequency)을 만들어내고 여기에 외부의 phase input을 더해 sine table에 넣고 그 결과에 또 다른 envelope control을 두는 것이다.

예를 들어 1개의 operator가 있다고 치면, 이것은 오직 단일 주파수의 sine wave만 만들어내고 그 envelope를 컨트롤 해서 음의 특성을 만들어낸다고 보면된다. 여기에 최소로 MIDI에서 요구하는 modulation을 제공하려면 phase값을 특정 진폭으로 주기적으로 바꿔주는 요소가 필요하다. 이것을 개념적으로 생각해보면 같은 처리기가 하나 더 붙게되는 것과 같다.

따라서 이 블록이 2개 직렬 연결되어있다고 보면 최종으로 출력되는 sine wave의 phase 자체가 또 다른 sine 함수가 되기 때문에 이때부터 FM이라고 할 수가 있다. 엄밀히 말하면 time-varying phase 혹은 phase-oscillating 하다고 할 수 있는데, 간단히 생각해보면 음이 하나의 주파수에 고정되어있지 않고 좌우로 왔다갔다 하는 것이라고 보면된다. 해석하는 위치에 따라서 FM이 될 수도 있고 PM이 될 수도 있지만 어쨌든 이것은 중요하지 않다. amplitude가 아닌 phase에 조작을 가한다는 것이니까.

또 여기서 sine wave라고 말한 것은 앞서 이야기 한 waveform이라고 말해야 정확하다. 정확하게는 waveform table이 되어야 할텐데 sampling rate가 올라가는 것에 대한 signal quality를 고려하면 table이라기 보단 그냥 함수의 형태가 되어야 한다.

이것을 YM 시리즈 칩셋에서는 최대 4개를 둘 수가 있다. 알고리즘에 따라서 이들을 직렬, 병렬, 직병렬로 연결할 수 있다. 그 패턴은 어차피 H/W로 만들다보니 정해진 것 중에 하나로 선택해야 하는데, 대충 2개의 operator를 쓰면 직/병렬로 알고리즘 4개 (=2^2)중 하날 선택할 수 있고 4개면 16개 뭐 이런 식이다.

대충 예전에 신디사이저를 써봤던 경험을 되살리면 음색의 구성이 복잡해지면 이런 저런 기능을 쓸 수 없게 되었던 것이 다 이 처리기의 개수를 한정해놓았기 때문에 그랬구나 라는 것을 알 수 있다.

어쨌든 이 처리기의 개수, waveform의 개수, 총 채널의 개수가 칩 마다 정해져있었다. 정확히 알 수 없는 것은 이 operator라는 것의 개수를 한정해놓고 모든 채널이 총 개수 범위내에서 꺼내쓸 수 있도록 되어있는 것은 아닌 것 같다. 이를테면 9개 채널이 있고 총 18개의 operator가 있다고 하면 어떤 채널엔 4개를 가져가고 어떤 채널엔 1개씩 가져가고 해서 그 총합이 18개 이내이면 조합이 가능하게끔 만든 것은 아닌 것 같다.

어떻게 해석하면 이것은 recursive function 같이 생각이 되기도 한다. 어쨌든 가장 마지막의 operator가 어떤 주파수를 갖느냐에 따라 음이 결정된다. 메뉴얼에서는 이것을 carrier라고 부른다. phase 텀에 들어가는 operator는 modulator가 되고.

MIDI의 modulation을 어떻게 적용하는지는 찾을 수가 없다. 이것은 소프트웨어적인 운용에 관련된 것이라.

Envelope control

칩의 모델에 따라 조금씩 다른 것 같은데 기본적으로 아래와 같이 구성된다.

1) Attach 2) Decay (Decay1) 3) S (Decay2) 4) R (Release)

이 때 사용하는 테이블/알고리즘은 역시 음색을 결정하는 것이라 원본 음색을 그대로 유지하려면 그대로 이용해야 한다.

C codes

아래의 링크를 이용하면 기본적인 source code를 이용할 수 있는데, 문제는 이 코드는 사실상 H/W를 reverse engineering한 것이라 모델링의 정확도에 초점을 맞추고 있다는 것이다. 이를테면 신호처리상의 정확도를 생각하면 내용을 대폭 수정해야 한다. 특정 테이블들은 음색에 매우 큰 영향을 미치기 때문에 있는 그대로 사용해야 하는 것들도 있다.

https://github.com/aaronsgiles/ymfm

음의 발생 등등..

이것을 instrument로 만들면 일단 채널의 한계를 없에는 것이 바람직하고 하나의 음을 내는 처리 단위를 객체로 구분하고 키 입력을 받으면 생성해서 release가 다 끝난 음은 자동소멸하는 식으로 가게 되므로 알고리즘이 복잡한 패치를 사용하고 많은 음을 누르게 되면 시스템의 부하/메모리 사용량이 증가하는 식으로 구현이 될 것이다.

YM 시리즈에 보면 percussion을 처리하는 채널이 몇 개 있는데, 사실 이 부분은 sample data에 의존해야 하는 부분이라 칩을 모델링하겠다는 것이 목적이 아니라면 구태여 만들어넣을 이유는 없을 것 같다.