VAD-фильтр

Последнее обновление: 29.01.2017

При записи звука иногда возникает необходимость записи только человеческого голоса, не записывая при этом какие-то посторонние звуки, шумы и т.д. Для этого используются так называемые VAD-фильтры (Voice Activity Detection), которые позволяют выявлять, если ли голос на некотором звуковом отрезке.

Итак, ранее в статье Запись звука мы рассмотрели запись звука с микрофона с приминением библиотеки NAudio. Используя ее API создадим наш детектор голоса. Код нашего фильтра голоса будет выглядеть следующим образом:

// Обработчка речи - вычисляем, есть ли сама речь на звуковом отрезке
        private bool ProcessData(WaveInEventArgs e)
        {
			// Порог для вычисления наличия речи
			private double porog = 0.02;
            bool result = false;
            bool Tr = false;
            double Sum2 = 0;
            int Count = e.BytesRecorded / 2;
            for (int index = 0; index < e.BytesRecorded; index += 2)
            {
                double Tmp = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]);
                Tmp /= 32768.0;
                Sum2 += Tmp * Tmp;
                if (Tmp > porog)
                    Tr = true;
            }
            Sum2 /= Count;
            if (Tr || Sum2 > porog)
            { result = true; }
            else
            { result = false; }
            return result;
        }

Итак, функция ProcessData возвращает нам булевое логическое значение, показывающее определена или нет речь на некотором отрезке звука. Чтобы получить звук, мы передаем аргумент типа WaveInEventArgs. Этот тип принадлежит библиотеки NAudio. На самом деле он нам нужен, потому что содержит буфер звука, который мы в последствии используем: e.Buffer. То есть фактически мы можем в качетсве параметра передать тот массив звуковых данных, который был нами получен с микрофона.

Следует отметить, что мы используем некоторый порог. В данном случае он равен 0.02 (private double porog = 0.02;) и может варьироваться и устанавливаться экспериментальным путем в зависимости от ситуации.

Получая значение типа short, а затем double мы сравниваем полученное значение с порогом и на основании сравнения потом узнаем, есть ли звук на данном речевом отрезке или нет.

После этого модифицируем код процедуры waveIn_DataAvailable из ранее упомянутой статьи Запись звука, чтобы обрабатывался лишь тот звуковой материал, на котором наш фильтр выявит речь:

//получение данных из входного буфера для распознавания
void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new EventHandler(waveIn_DataAvailable), sender, e);
    }
    else
    {
        //переменная для обозначения начала распознавания речевого отрезка
        bool result = ProcessData(e);
        // Если записываемый отрезок содержит речь
        if (result == true)
        {
            // обрабатываем звуковые данные
        }
        else
        {
			// если речь не определена на звуковом отрезке
        }
    }
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850