Эхо довольно простое. Вам нужна линия задержки и небольшое умножение. Предполагая, что один канал и звук уже представлены в формате с плавающей запятой, линия задержки будет выглядеть примерно так (в C-подобном псевдокоде):
int LENGTH = samplerate * seconds; //seconds is the desired length of the delay in seconds
float buffer[ LENGTH ];
int readIndex = 0, writeIndex = LENGTH - 1;
float delayLine.readNext( float x ) {
float ret = buffer[readIndex];
++readIndex;
if( readIndex >= LENGTH )
readIndex = 0;
return ret;
}
void delayLine.writeNext( float x ) {
buffer[ writeIndex ] = x;
++writeIndex;
if( writeIndex >= LENGTH )
writeIndex = 0;
}
Не забудьте инициализировать буфер всеми нулями.
Так что это ваша линия задержки. Основное использование будет таким:
float singleDelay( float x ) {
delayLine.writeNext(x);
return delayLine.readNext( x );
}
Но особой разницы вы не услышите: просто это вылезет позже. Если вы хотите услышать одно эхо, вам понадобится что-то вроде этого:
float singleEcho( float x, float g ) {
delayLine.writeNext(x);
return x + g * delayLine.readNext( x );
}
где g — некоторая константа, обычно между нулем и единицей.
Теперь скажите, что вам нужен поток эха: ПРИВЕТ... Привет... привет... х... вот так. Вам просто нужно сделать немного больше работы:
float echo( float x, float g ) {
float ret = x + g * delayLine.readNext( x );
delayLine.writeNext( ret );
return ret;
}
Обратите внимание, как на этот раз вывод всего этого возвращается обратно в линию задержки, а не на вход. В этом случае очень важно, чтобы |g| ‹ 1.
Здесь вы можете столкнуться с проблемами денормалей. Я не могу вспомнить, была ли это проблема на iOS, но я так не думаю.
person
Bjorn Roche
schedule
03.08.2012