Цифровая обработка сигналов в Scilab: как удалить шум в аудиозаписи с помощью фильтров обработки звука

Добавлено 22 ноября 2018 в 05:15

Данная статья представляет собой введение в сложную тему снижения шума в аудиосигналах с помощью цифровой обработки сигналов.

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

Оптимизация качества звука – это то, что должно выполняться во всей системе – от микрофона до динамика и всего между ними. В данной статье мы рассмотрим блок DSP (ЦОС, цифровой обработки сигналов), в котором цифровые звуковые сигналы модифицируются с помощью тщательно разработанных алгоритмов. Это всего лишь одна часть в цепочке аудиосигнала, но эта часть очень важна, потому что цифровая обработка сигналов универсальна и может смягчать недостатки, вводимые другими компонентами.

Прежде чем двигаться дальше, взгляните на следующие ресурсы для ознакомления с контекстом и связанной информацией:

Вспомогательная информация

Предыдущие статьи о цифровой обработке сигналов в Scilab

Уменьшение шипения

Цель данной статьи – удалить фоновый шум при записи человека. Тип шума, о котором я говорю, называется «шипением», и его гораздо проще объяснить на примере, чем словами. Следующий аудиофайл – это запись, в которой я читаю первые две строки «Ворона» Эдгара Аллан По. Шипение присутствует во всей записи, и это особенно заметно в конце, после того, как я перестаю говорить.

Значительно уменьшить шипение – непростая задача. В этой статье мы будем использовать фильтры, которые являются простыми, но не особенно эффективными.

Загрузка и анализ аудиофайла

Следующая команда преобразует ваш WAV файл в переменные Scilab:

[OriginalAudio, Fs] = wavread("C:\Users\Robert\Documents\Audio\OnceUponaMidnightDreary.wav");

Если вы читали статью «Как выполнить частотную модуляцию оцифрованным аудиосигналом с помощью Scilab», вы знакомы с командой wavread(). Возможно, вы заметили, что эта версия немного отличается. Если вы включаете две возвращаемые переменные, вторая из них будет содержать частоту дискретизации аудиофайла. Это удобно потому, что из предыдущих статей известно, что дискретный по времени анализ в частотной области требует знания частоты дискретизации.

Чтобы подтвердить правильность записи, вы можете использовать следующую команду:

playsnd(OriginalAudio, Fs)

Теперь давайте посмотрим на спектральные характеристики этого аудиосигнала. Разумеется, мы могли бы использовать команду fft(), а затем по данным построить график в соответствии с процедурой, представленной в предыдущих статьях. Однако мы можем немного упростить себе жизнь, воспользовавшись командой Scilab analyze(). Если вы передадите этой функции массив, представляющий оцифрованный сигнал, вместе с частотой дискретизации сигнала, она создаст график в частотной области, который уже будет иметь горизонтальную ось, настроенную для отображения частоты в герцах. Вы также указываете минимальную и максимальную частоты и количество выборок. Например:

Fmin = 20;
Fmax = 20e3;
analyze(OriginalAudio, Fmin, Fmax, Fs, length(OriginalAudio))
Результат команды analyze() при установленной максимальной частоте 20 кГц
Результат команды analyze() при установленной максимальной частоте 20 кГц
Fmax = 2e3;
analyze(OriginalAudio, Fmin, Fmax, Fs, length(OriginalAudio))
Результат команды analyze() при установленной максимальной частоте 2 кГц
Результат команды analyze() при установленной максимальной частоте 2 кГц

Анализ шипения

План состоит в том, чтобы использовать фильтр для уменьшения шипения. Фильтр должен быть спроектирован в соответствии с частотным содержимым шипения, и мы можем определить это частотное содержимое, посмотрев на спектр аудиофрагмента, который имеет только фоновый шум. В моем файле я останавливаюсь примерно на 9-ой секунде, а запись заканчивается на 12-ой секунде. Итак, давайте извлечем данные, соответствующие звуку, с 10-ой по 12-ую секундам, а затем посмотрим на график в частотной области.

Fmax = 20e3;
OriginalAudio_NoiseOnly = OriginalAudio(10*Fs : 12*Fs);
playsnd(OriginalAudio_NoiseOnly, Fs)     // чтобы подтвердить, что фрагмент содержит только фоновый шум
analyze(OriginalAudio_NoiseOnly, Fmin, Fmax, Fs, length(OriginalAudio_NoiseOnly))
Спектр сигнала во фрагменте аудиофайла, где содержится только фоновый шум (максимальная частота 20 кГц)
Спектр сигнала во фрагменте аудиофайла, где содержится только фоновый шум (максимальная частота 20 кГц)
Fmax = 1e3;
analyze(OriginalAudio_NoiseOnly, Fmin, Fmax, Fs, length(OriginalAudio_NoiseOnly))
Спектр сигнала во фрагменте аудиофайла, где содержится только фоновый шум (максимальная частота 1 кГц)
Спектр сигнала во фрагменте аудиофайла, где содержится только фоновый шум (максимальная частота 1 кГц)

Как вы можете видеть, фоновый шум имеет довольно постоянную амплитуду в широком диапазоне частот и более высокую амплитуду в пределах небольшой полосы ниже 100 Гц. Существует также компонент шума с относительно высоким уровнем на частоте 60 Гц. Я нахожусь в Северной Америке, и моя аудиосистема окружена питанием 60 Гц, поэтому это подтверждает, что команда analyze() дает нам точную информацию о частотах.

Проектирование и реализация фильтра

Для этой задачи мы будем использовать графический инструмент проектирования FIR фильтров (КИХ фильтр, фильтр с конечной импульсной характеристикой) в Scilab.

FIR_coefficients = wfir();

К сожалению, мы не можем много чего сделать с обычной фильтрацией. Я не думаю, что будет хорошей идеей попытаться удалить низкочастотный шум или всплеск на 60 Гц, потому что исходный сигнал имеет большую спектральную составляющую с центром около 80 Гц. Конечно, мы можем выполнить фильтрацию нижних частот, но мы должны решить, где разместить частоту среза.

Когда я смотрю на спектр исходного сигнала, у меня создается впечатление, что шум делает доминирующий вклад, начиная примерно с 5 кГц.

Настройка КИХ-фильтра нижних частот с частотой среза 5 кГц
Настройка КИХ-фильтра нижних частот с частотой среза 5 кГц
Амплитудно-частотная характеристика полученного КИХ-фильтра нижних частот
Амплитудно-частотная характеристика полученного КИХ-фильтра нижних частот

После того, как вы нажмете OK, коэффициенты будут сохранены в переменной FIR_coefficients, и затем мы сможем применить фильтр через свертку. Для этого используется команда convol().

FilteredAudio = convol(FIR_coefficients, OriginalAudio);
analyze(FilteredAudio, Fmin, Fmax, Fs, length(FilteredAudio))
Спектр аудиосигнала после фильтрации
Спектр аудиосигнала после фильтрации

Как вы можете видеть, мы успешно подавили высокочастотный контент. Вот получившийся звук:

Я думаю, что громкость шипения уменьшилась, хотя результаты далеки от впечатляющих – шипение всё еще очень заметно, и качество голоса было изменено. Он кажется более плоским и отдаленным – больше похоже на запись и меньше на реальную жизнь. Полагаю, это неудивительно, поскольку некоторые едва различимые характеристики звука были утеряны, когда мы удалили эти верхние частоты.

Две следующие записи дают вам представление о том, как на качество звука влияет более высокая или более низкая частота среза (fср).

fср = 7 кГц

fср = 3 кГц

Заключение

В данной статье мы исследовали характеристики шума типовой записи голоса и попытались улучшить качество звука, используя фильтр нижних частот. Если у вас есть какие-либо идеи о том, как добиться лучшего подавления шипения с помощью фильтров, поделитесь своими мыслями в комментариях ниже.


На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.


Сообщить об ошибке