37

Próbuję zaimplementować pewne cechy chip dźwięku Yamaha YM3812 (aka OPL2 http://en.wikipedia.org/wiki/YM3812) w JavaScript używając Audiolet (biblioteka synteza, http://oampo.github.io/Audiolet/api.html)Co jest nie tak z tym prostym projektem syntezy FM?

Audiolet pozwala zbudować syntezator w postaci wykresu węzłów (oscylatory , DSP, generatory kopert itp.).

OPL2 ma dziewięć kanałów z dwoma operatorami (oscylatorami). Zwykle jeden oscylator w każdym kanale moduluje częstotliwość drugiego. Aby to zasymulować, mam zbudował sieć węzłów dla każdego kanału:

łańcucha węzeł Synth (jeden z dziewięciu kanałów) tworzenie łańcucha

OPL2 channel as implemented

Node i kodu połączenia:

var FmChannel = function(audiolet) { 
    this.car = new ModifiedSine(audiolet); 
    this.carMult = 1; 
    this.setCarrierWaveform(this.SIN); 
    this.mod = new ModifiedSine(audiolet); 
    this.modMult = 1; 
    this.setModulatorWaveform(this.SIN); 
    this.modMulAdd = new MulAdd(audiolet); 
    this.carGain = new Gain(audiolet); 
    this.carEnv = new ADSREnvelope(audiolet, 0, 0.1, 0.1, 0.1, 0.1, 
     function() { 
      this.carEnv.reset(); 
     }.bind(this) 
    ); 
    this.carAtten = new Multiply(audiolet); 
    this.modGain = new Gain(audiolet); 
    this.modEnv = new ADSREnvelope(audiolet, 0, 0.1, 0.1, 0.1, 0.1, 
     function() { 
      this.modEnv.reset(); 
     }.bind(this) 
    ); 
    this.modAtten = new Multiply(audiolet); 

    this.modEnv.connect(this.modGain, 0, 1); 
    this.mod.connect(this.modGain); 
    this.modGain.connect(this.modAtten); 
    this.modAtten.connect(this.modMulAdd); 
    this.modMulAdd.connect(this.car); 
    this.carEnv.connect(this.carGain, 0, 1); 
    this.car.connect(this.carGain); 
    this.carGain.connect(this.carAtten); 
    // connect carAtten to the mixer from outside 
}; 

kiedy jednak zestaw parametrów modulatora i nośnika węzłów (przebiegi oscylatora stosunku częstotliwości ATTEN Parametry ADSR) i noty wywołujące, dane wyjściowe niewiele przypominają godnego emulatora OPL2 z mniej więcej tymi samymi parametrami. Niektóre dźwięki są w parku. Inne są dość nieprzyjemne.

Mam kilka pomysłów na temat dalszego postępowania (myślę, że narysowanie wyniku na różnych etapach byłoby dobrym punktem wyjścia), ale mam nadzieję, że ktoś doświadczony może wskazać mi właściwy kierunek, lub wskazać na coś oczywistego z tym, co robię. Nie mam przetwarzania sygnału ani silnego tła matematycznego. Nie mam głębokiego intuicyjnego rozumienia FM.

Niektóre kwestie Podejrzewam są:

1) Moja implementacja FM (jak pokazano powyżej) jest fundamentalnie błędne. Ponadto, nie może być problemem w funkcji gdzie grać notatkę (ustawienie częstotliwości oscylatora, a skala i offset modulatora przed wyzwalania obwiedni ADSR):

FmChannel.prototype.noteOn = function (frq) { 
    var Fc = frq*this.carMult; 
    this.car.reset(Fc); 
    this.mod.reset(frq*this.modMult); 
    // scale and offset modulator from range (-1, 1) to (0, 2*Fc) 
    // (scale and offset is after ADSR gain and fixed attenuation is applied) 
    this.modMulAdd.mul.setValue(Fc); 
    this.modMulAdd.add.setValue(Fc); 
    this.carEnv.reset(); 
    this.modEnv.reset(); 
    this.carEnv.gate.setValue(1); 
    Thethis.modEnv.gate.setValue(1); 
}; 

2) Wyjście z syntezatorów FM mogą być bardzo wrażliwe do niewielkich różnic w kształcie koperty modemu ADSR (proszę mi powiedzieć, czy to prawda!), a moje koperty ADSR są w najlepszym przybliżeniu co najwyżej z ADSRs w prawdziwym OPL2. Mojej implementacji brakuje również niektórych cech, które wydają się stosunkowo mało istotne (np. Skalowanie klawisza), ale które mogą znacząco wpłynąć na dźwięk syntezatora FM (znowu nie jestem pewien).

+4

Patrząc na swój obraz, modulator powinien być połączony z częstotliwością nośną i nie powinien się podnosić (tak: https://en.wikipedia.org/wiki/Frequency_modulation#/media/File:Amfm3-en-de.gif). – Elric

+0

Zwykle powinieneś być ostrożny ze stopniem wzmocnienia modulatora i nie stosować zbyt dużego wzmocnienia, a tym samym modulacji. Jeśli modulacja jest zbyt duża, otrzymujesz "nieprzyjemne dźwięki" z modulacją dominującą nad operatorem. Nie jestem pewien, czy to właśnie opisujesz. – noumenal

+0

Elric, na podstawie diagramu z pewnością wygląda na to, że modulator jest powiązany z zyskiem. Od dawna pracowałem nad tym lub patrzyłem na Audiolet, że nie jestem pewien, czy to właśnie się dzieje! Muszę się w to zagłębić. – bsa

Odpowiedz

1

Większość syntezatorów ze stoickim "FM" faktycznie moduluje fazę (PM, patrz https://en.wikipedia.org/wiki/Phase_modulation). Są pewne korzyści (głównie prowadzące do bardziej stabilnego dźwięku w szerokim zakresie tonalnym). OPL2 może również używać tego, nie znalazłem żadnych wyraźnych dowodów, ale artykuł Wikipedii również używa terminu "modulacja fazy".

Krótko mówiąc, wiele syntezatorów muzycznych oznaczonych "FM" w rzeczywistości zawierało "PM", więc możesz spróbować pójść z tym i sprawdzić, czy lepiej pasuje do oczekiwanych dźwięków OPL2.

Od szybkiego spojrzenia na źródło Audiolet, zgaduję, że oscilator robi prawdziwy FM, więc być może trzeba go wymienić i dodać wejście fazowe, aby umożliwić modulację fazy.

Zasadniczo, linia

output.samples[0] = Math.sin(this.phase); 

wykorzystywane przez Sine z oscilator nośnej musiałby czytać coś jak

output.samples[0] = Math.sin(this.phase+phase_offset); 

z phase_offset kontrolowanego przez mod oscilator zamiast częstotliwości.

+0

Słynna klawiatura Yamaha DX7, w tym samym czasie przez tego samego producenta, co OPL2, została również oznaczona jako "synteza FM" pomimo stosowania modulacji fazy. – dronus

+0

Dzięki za odpowiedź. Masz rację, OPL używa modulacji fazowej i myślałem, że moja implementacja robi "prawdziwy" FM, ale od dawna nie patrzyłem na to, naprawdę nie mogę powiedzieć teraz :). Rozumiem, że dla fal sinusoidalnych modulacja fazowa i modulacja częstotliwości są równoważne, więc mogłem osiągnąć podobny dźwięk w ten sposób. – bsa

+0

Nie, FM i PM różnią się znacznie od udostępniania wielu właściwości. Jednak tymczasowe zmiany częstotliwości integrują się z czasem dla FM, aby dodać ciągłe przesunięcie fazowe. W przypadku PM, tymczasowa modulacja dodaje tymczasowe przesunięcie fazowe. – dronus