При записи звука иногда возникает необходимость записи только человеческого голоса, не записывая при этом какие-то посторонние звуки, шумы и т.д. Для этого используются так называемые 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 { // если речь не определена на звуковом отрезке } } }