Оглавление.
Введение. Общие вопросы компьютерного распознавания и порождения речи.
1. Программирование звука в Windows.
2. Основы цифровой обработки звуковых сигналов.
3. Определение параметров речевого сигнала.
4. Алгоритмы распознавания.
5. Использование Microsoft Speech API 5.1 для синтеза
и распознавания речи.
6. Использование Microsoft Speech API 4.0 для синтеза
речи.
Ссылки.
Об авторе.
|
|
Компьютерное распознавание и порождение речи
Глава 3. Определение параметров речевого сигнала.
3.3. Форманты речевого сигнала.
Важнейшим параметром, характеризующим спектр (распределение энергии или амплитуды по частотам) речевого сигнала являются форманты, которые определяют как концентрацию энергии в ограниченной частотной области. Форманта характеризуется частотой, шириной и амплитудой. За частоту форманты принимают частоту максимальной амплитуды в пределах форманты. Другими словами, форманта – это некоторый амплитудный всплеск на графике спектра, а его частота – частота пика этого всплеска.
На рисунке видно четыре форманты с частотами F0, F1, F2, F3.
Форманта F0 называется также частотой основного тона речевого сигнала.
Форманты F1 – F6 определяют концентрацию энергии речевого сигнала по частоте и характеризуют вокализованные (как правило, гласные) звуки. Форманты начиная с F3 несут информацию о дикторе и широко используются в системах распознавания диктора.
Поговорим об алгоритме выделения формант в речевом сигнале. Как и остальные параметры речевого сигнала, форманты быстро меняются в течение времени, поэтому принято снимать их на отрезке звукового сигнала 10-20 мс, считая что сигнал на таком отрезке примерно стационарен (постоянен).
На первом этапе, естественно, берется преобразование Фурье от исходного сигнала, чтобы получить сигнал спектра.
Далее обычно поступают так.
Известно, что первая форманта (частота основного тона) лежит в промежутке от 50 Гц (у взрослого мужчины) до 300 Гц ( у детей и некоторых женщин). Кроме того известно, что амплитуда каждой последующей форманты ниже, чем предыдущей, а их частоты равны частоте основного тона умноженного на целое число (2 для F1, 3 для F2 и так далее).
Таким образом мы можем найти максимальное значение амплитуды сигнала на отрезке от 50 Гц до 300 Гц, после чего умножить эту частоту на 2, найти максимальное значение амплитуды в некоторой окрестности этой точки, проверить является ли она максимумом амплитуды в некоторой большей окрестности. Если это предположение верно, то мы нашли частоту второй форманты (F1). Если нет – второй форманты у сигнала нет.
Далее умножаем частоту основного тона на три и повторяем все вышеприведенные шаги для третьей форманты. Потом повторяем для всех остальных формант. Как правило, вычисляют от 4 до 6 формант.
Приведем алгоритм выделения формант речевого сигнала на языке Си.
// Получить m формант сигнала в домене времени x длиной n, N – частота
// Возвращает указатель на массив формант
double* GetFormants(double* x, int n, int m, int N)
{
double* Res=(double*)malloc(m*sizeof(double));
double* Mag=(double*)malloc((n/2+1)*sizeof(double));
ShortComplex *source=(ShortComplex*)malloc(n*sizeof(ShortComplex));
for (int i=0;i source[i].re=x[i];
source[i].im=0;
}
//Вычислим быстрое преобразование Фурье
fft(source,8,false);
//Определим абсолютные значения амплитуд в спектре
for(i=0;i<(n/2+1);i++){
Mag[i]=sqrt(source[i].re*source[i].re+source[i].im*source[i].im);
}
//Определим индексы интервала для поиска первой форманты
int left_ind=(int)((50*n)/N);
int right_ind=(int)((300*n)/N);
//Находим частоту первой форманты
double dMax=Mag[left_ind];
int ind_max=left_ind;
for(i=left_ind+1;iright_ind;i++)
{
if(Mag[i]dMax)
{
dMax=Mag[i];
ind_max=i;
}
}
Res[0]=(N*ind_max)/n;
int first_ind_max=ind_max;
//Найдем частоты остальных формант. Если не находим – заносим 0 в массив результата.
for(int j=1;jm;j++)
{
left_ind=first_ind_max*(j+1)-int(first_ind_max/6);
right_ind=first_ind_max*(j+1)+int(first_ind_max/6);
dMax=Mag[left_ind];
ind_max=left_ind;
for(i=left_ind+1;iright_ind;i++ )
{
if(Mag[i]>dMax)
{
dMax=Mag[i];
ind_max=i;
}
}
int cur_ind_max=ind_max;
left_ind=first_ind_max*(j+1)-int(first_ind_max/3);
right_ind=first_ind_max*(j+1)+int(first_ind_max/3);
for(i=left_ind+1;i {
if(Mag[i]dMax)
{
Res[j]=0;
break;
}
}
Res[j]=(N*ind_max)/n;
}
return(Res);
}
|
|