Что не так с этим простым дизайном FM-синтезатора?

Я пытаюсь реализовать некоторые функции звукового чипа Yamaha YM3812 (также известного как OPL2 http://en.wikipedia.org/wiki/YM3812) в JavaScript, используя Audiolet (библиотека синтеза, http://oampo.github.io/Audiolet/)

Audiolet позволяет вам построить синтезатор в виде графа узлов (осцилляторы, DSP, генераторы огибающей и т. Д.).

OPL2 имеет девять каналов с двумя операторами (генераторами) каждый. Обычно один генератор в каждом канале модулирует частоту другого. Чтобы смоделировать это, я построил цепочку узлов для каждого канала:

Цепочка синтезирующих узлов (один из девяти каналов)

Канал OPL2 как реализовано

Создание цепочки узлов и код подключения:

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
};

Однако, когда я устанавливаю параметры узлов модулятора и несущей (формы сигналов генератора, относительные частоты, затухание, параметры ADSR) и запускаю примечания, выходные данные очень мало похожи на приличный эмулятор OPL2 с примерно такими же параметрами. Некоторые звуки находятся на стадионе. Другие довольно неприятные.

У меня есть некоторые идеи о том, как действовать (я думаю, что вывод результатов на разных этапах был бы хорошей отправной точкой), но я надеюсь, что кто-то опытный может указать мне верное направление или указать на что-то явно неправильное с тем, что я ". я делаю. У меня нет обработки сигналов или сильных математических знаний. У меня нет глубокого интуитивного понимания FM.

Я подозреваю некоторые проблемы:

1) Моя реализация FM (как показано выше) в корне неверна. Кроме того, может быть проблема в функции воспроизведения ноты (установите частоты генератора, масштабируйте и сдвигайте модулятор перед запуском конвертов 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) Вывод FM-синтезаторов может быть очень чувствительным к небольшим различиям в форме огибающей модулятора ADSR (пожалуйста, скажите мне, если это правда!), И мои огибающие ADSR являются грубыми приближениями в лучшем случае ADSR в реальном OPL2. В моей реализации также отсутствуют некоторые функции, которые кажутся относительно незначительными (например, масштабирование клавиш), но которые могут существенно повлиять на звучание синтезатора FM (опять же, я не уверен).

1 ответ

Большинство синтезаторов, помеченных как "FM", на самом деле имеют фазовую модуляцию (см. https://en.wikipedia.org/wiki/Phase_modulation). Есть некоторые преимущества (в основном приводящие к более стабильному звучанию на большом тональном диапазоне). OPL2 также может использовать это, я не нашел четких доказательств, но в статье Википедии также используется термин "фазовая модуляция".

Короче говоря, многие музыкальные синтезаторы с пометкой "FM" на самом деле имели "PM", так что вы можете попробовать пойти на это и проверить, подходит ли он лучше ожидаемых звуков OPL2.

От быстрого взгляда до источника Audiolet, я думаю, Sine Осциллятор работает на частоте FM, поэтому вам, возможно, придется заменить его и добавить фазовый вход, чтобы обеспечить фазовую модуляцию.

В основном, линия

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

использован Sine генератора несущей должен был бы прочитать что-то вроде

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

с phase_offset контролируется генератором мод вместо частоты.

Другие вопросы по тегам