Я пытаюсь создать ревербератор FDN в WebAudio, следуя этой статье.
Существует упрощенная реализация FDN Householder, которая использует общий коэффициент обратной связи для всех задержек и выглядит довольно стабильной.
Однако, когда я пытаюсь реализовать более общий случай, смешанный с матрицей, я не могу сделать его стабильным.
Я вложил большую часть кода, чтобы сузить проблему, и поместил ее в JSFiddle.
EDIT: предупреждение, большой объем в неустойчивом корпусе.
Разница сводится к следующему:
var feedback = context.createGain();
feedback.gain.value = gainValue;
for(var i=0; i<n; i++) {
this.delays[i].connect(feedback);
feedback.connect(this.delays[i]);
}
По сравнению с:
for(var i=0; i<n; i++) {
for(var o=0; o<n; o++) {
var feedback = context.createGain();
feedback.gain.value = gainValue;
this.delays[i].connect(feedback);
feedback.connect(this.delays[o]);
}
}
Когда я использую общую обратную связь GainNode для всех задержек, она работает нормально. Когда я создаю индивидуальную обратную связь GainNodes для всех задержек, используя тот же метод gainValue, он становится неустойчивым.
Что я делаю неправильно?
EDIT: Разъяснение из статьи.
Как упоминалось в п. 3.4, "идеальный" поздний резонанс реверберации должен напоминать экспоненциально затухающий шум [314]. Поэтому полезно при проектировании ревербератора начать с бесконечного времени реверберации ("случай без потерь") и работать над тем, чтобы сделать ревербератор хорошим "генератором шума". Такая исходная точка [часто] называется прототипом без потерь [153,430]. Когда в импульсном отклике прототипа без потерь слышен ровный шум, можно затем работать над получением желаемого времени реверберации в каждой частотной полосе (как будет описано ниже в п. 3.7.4).
В коде это означает:
for(var i=0; i<n; i++) {
for(var o=0; o<n; o++) {
var feedback = context.createGain();
feedback.gain.value = gainValue/9;
this.delays[i].connect(feedback);
feedback.connect(this.delays[o]);
}
}
Я могу повторно использовать этот код когда-нибудь правильно??? Если я устанавливаю n до 30, я получаю вид звука в цимбале.
Узлы усиления добавляют громкость друг к другу. Если вы используете несколько узлов усиления, вам нужно разбить их на количество активных узлов усиления.
Так что, если у вас есть 10 узлов усиления, одновременно использующих громкость для узла усиления, это значение /10 (количество активных узлов усиления). Вам необходимо отредактировать значение узлов усиления до и до нового значения. Поэтому лучше всего сохранить все узлы Gain в массиве и перебрать его.
Я не пробовал, но думаю, что это сработает. Это физически совершенно неудобно, потому что, если у вас десять человек, плачущих в одной комнате, db-Meter все еще так же громко, как если бы вы плакали. Попытайтесь больше вычислить узлы усиления математическим способом, чтобы они добавляли сигнал друг к другу.
Кстати, ваш ревербератор - допинг.