В этом примере показано, как применить адаптивные фильтры, чтобы сигнализировать, что разделение с помощью структуры вызвало адаптивный усилитель линии (ALE). В адаптивном улучшении линии измеренный сигнал x (n) содержит два сигнала, неизвестный сигнал интереса v (n), и почти периодическая шумовая ЭТА сигнала (n).
Цель состоит в том, чтобы удалить шумовой сигнал из измеренного сигнала получить сигнал интереса.
Автор (авторы): Скотт К. Дуглас
Мы сначала загрузим в сигнале интереса, короткого ролика от хора Аллилуйи Генделя.
audioReader = dsp.AudioFileReader('handel.ogg','SamplesPerFrame',44100); timeScope = timescope('SampleRate',audioReader.SampleRate,... 'YLimits',[-1,1],'TimeSpanSource','property','TimeSpan',1); while ~isDone(audioReader) x = audioReader() / 2; timeScope(x); end
Можно слушать сигнал интереса с помощью средства записи аудио устройства.
release(audioReader); audioWriter = audioDeviceWriter; while ~isDone(audioReader) x = audioReader() / 2; audioWriter(x); end
Давайте теперь сделаем периодический шумовой сигнал - синусоида с частотой 1 000 Гц.
sine = dsp.SineWave('Amplitude',0.5,'Frequency',1000,... 'SampleRate',audioReader.SampleRate,... 'SamplesPerFrame',audioReader.SamplesPerFrame);
Теперь давайте построим 10 мс этой синусоиды выше. Это показывает 10 периодов в 10 мс, как это должно.
eta = sine(); Fs = sine.SampleRate; plot(1/Fs:1/Fs:0.01,eta(1:floor(0.01*Fs))); xlabel('Time [sec]'); ylabel('Amplitude'); title('Noise Signal, eta(n)');
Периодический шум является чистым тоном. Следующий код проигрывает одну секунду (одна система координат 44 100 выборок) шумового сигнала.
eta = sine(); release(audioWriter); audioWriter(eta);
Сигнал, что мы на самом деле измеряемся, является суммой этих двух сигналов, и мы вызываем этот сигнал s (n). График s (n) показывает, что конверт музыкального сигнала в основном затенен. Слушая 3 вторых клипа от измеренного сигнала, шум является явно видным...
release(audioReader); release(timeScope); release(audioWriter); count = 1; while count < 4 s = (audioReader() / 2) + sine(); timeScope(s); audioWriter(s); count = count + 1; end
Адаптивный усилитель линии (ALE) основан на прямой концепции линейного предсказания. Почти периодический сигнал может быть отлично предсказан с помощью линейных комбинаций его прошлых выборок, тогда как апериодический сигнал не может. Так, задержанная версия измеренного сигнала s (n-D) используется в качестве ссылочного входного сигнала x (n) к адаптивному фильтру, и желаемый сигнал d (n) ответа сделан равным s (n). Параметры, чтобы выбрать в такой системе являются задержкой сигнала D и длиной фильтра L используемый в адаптивной линейной оценке. Сумма задержки зависит от объема корреляции в сигнале интереса. Поскольку у нас нет этого сигнала (если бы мы сделали, нам не был бы нужен ALE!), мы только выберем значение D=100 и варьироваться он позже. Такой выбор предполагает, что выборки Хора Аллилуйи являются некоррелироваными, если они - больше, чем приблизительно 12 мс независимо. Кроме того, мы выберем значение L=32 для адаптивного фильтра, несмотря на то, что это также могло быть изменено.
D = 100; delay = dsp.Delay(D);
Наконец, мы будем использовать некоторый блок адаптивные алгоритмы, которые требуют, чтобы длины векторов для x (n) и d (n) были целочисленными множителями длины блока. Мы выберем длину блока N=49, с которого можно начать.
Первый алгоритм, который мы исследуем, является LMS-алгоритмом Блока. Этот алгоритм похож на известный least-mean-square (LMS) алгоритм, за исключением того, что это использует обновления коэффициента общей полноты вместо содействующих обновлений выборки выборкой. LMS-алгоритму Блока нужна длина фильтра, длина блока N и значение размера шага mu. Как мы выбираем mu? Давайте запустимся со значения mu = 0.0001 и давайте совершенствуем его вскоре.
L = 32; N = 49; mu = 0.0001; blockLMSFilter = ... dsp.BlockLMSFilter('Length',L,'StepSize',mu,'BlockSize',N);
Выходной сигнал y (n) должен в основном содержать периодическую синусоиду, тогда как сигнал ошибки e (n) должен содержать музыкальную информацию, если мы сделали все правильно. Поскольку у нас есть исходный музыкальный сигнал v (n), мы можем построить e (n) по сравнению с v (n) на том же графике, показанном выше наряду с остаточным сигналом e (n)-v (n). Похоже, что система сходится приблизительно после 5 секунд адаптации с этим размером шага. Действительное доказательство, однако, получено путем слушания;
release(audioReader); release(timeScope); release(audioWriter); while ~isDone(audioReader) x = audioReader() / 2; s = x + sine(); d = delay(s); [y,e] = blockLMSFilter(s,d); timeScope(e); audioWriter(e); end
Заметьте, как синусоидальный шум затухает далеко медленно. Это поведение происходит из-за адаптации коэффициентов фильтра к их оптимальным значениям.
Теперь удаление чистой синусоиды от синусоиды плюс музыкальный сигнал не особенно сложно, если частота незаконной синусоиды известна. Простой 2D полюс, 2D нулевой фильтр метки может выполнить эту задачу. Так, давайте сделаем проблему немного тяжелее путем добавления модулируемого FM синусоидального сигнала как нашего источника шума.
eta = 0.5 * sin(2*pi*1000/Fs*(0:396899)' + 10*sin(2*pi/Fs*(0:396899)')); signalSource = dsp.SignalSource(eta,... 'SamplesPerFrame',audioReader.SamplesPerFrame,... 'SignalEndAction','Cyclic repetition'); release(audioReader); release(timeScope); release(audioWriter); while ~isDone(audioReader) x = audioReader() / 2; s = x + signalSource(); timeScope(s); audioWriter(s); end
"Трель" в сигнале является явно слышимой. Фильтр метки фиксированного коэффициента не удалит модулируемую FM синусоиду. Давайте смотреть, может ли Блок основанный на LMS ALE. Мы увеличим значение размера шага к mu=0.005, чтобы помочь ALE отследить изменения шумового сигнала.
mu = 0.005; release(blockLMSFilter); blockLMSFilter.StepSize = mu;
Мы теперь фильтруем шумный музыкальный сигнал с адаптивным фильтром и сравниваем ошибку с бесшумным музыкальным сигналом.
release(audioReader); release(timeScope); release(audioWriter); while ~isDone(audioReader) x = audioReader() / 2; s = x + signalSource(); d = delay(s); [y,e] = blockLMSFilter(s,d); timeScope([x,e]); audioWriter(e); end
release(audioReader); release(timeScope); release(audioWriter);