Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > КЛП-Спектр


Автор: КидерOK 18.5.2004, 16:29
Привет всем. Пишу программу по обработке речевых сигналов. Если реализация ДПФ и Полосовых Фильтров не составила труда, то вот с Коэффициентами Линейного Предсказания возник трабл

Может быть кто-то знает простой алгоритм для вычисления спектра речевого сигнала на основе линейного предсказания? Естесственно, алгоритм пишется на C/C++. Если кто-то знает, напишите пожалуйста кусок кода хотя бы для анализа текущего сегмента (окна).

Заранее спасибо

Автор: Guest 19.5.2004, 22:18
народ хелп горю

Автор: maxim1000 20.5.2004, 11:16
для этого надо сесть и немного пописать на бумажке...
z - оператор запаздывания
s - сигнал
A(z) - полином, соответствующий модели линейного предсказания
e=A(z^-1)s - ошибка линейного предсказания
E(w) - значение спектра сигнала e на частоте w
S(w) - соответственно для сигнала s
T - период дискретизации
тогда:
E(w)=A(exp(-iwT)S(w)
S(w)=E(w) / A(exp(-iwT))
|S(w)|=|E(w)| / |A(exp(-iwT))|
обычно в данной модели принимают |E(w)|=E - не зависит от w, т.е. e - сигнал типа "белый шум"
тогда получается:
|S(w)|=E / |A(exp(-iwT))|

Автор: Guest 29.5.2004, 16:11
Ну и как по этому описанию составить алгоритм? Это все теория, теории - полный интернет. А толковую библиотеку - днем с огнем.

Автор: maxim1000 29.5.2004, 19:47
1. берем кусок сигнала
2. находим такие коэффициенты полинома A, чтобы среднеквадратическая ошибка была наименьшей. Обычно это делают через автокорреляционную функцию - решают систему линейных уравнений: c(j+1)=a1*c(j)+a2*c(j-1)+...+am*c(j-m+1)
3. при определении коэффициентов полинома A также определяем среднеквадратическое значение сигнала ошибки
4. вычисляем модуль спектра |S(w)|=E / |A(exp(-iwT))|
Цитата
Это все теория, теории - полный интернет

ну так обычно в теории и дается алгоритм

Автор: podval 1.6.2004, 22:23
Алгоритм простой - решить уравнение, записанное в самом конце статьи (уравнение Юла-Уокера).
Коэффициенты от 1 до a(p) - искомые коэффициенты LPC-фильтра.
Добавлено @ 22:28
З.Ы. поскольку обрабатываешь речь, самый действенный способ - решить уравнение "в лоб".
Всякие "навороченные" методы, которые могут ускорить вычисления, обладают плохой устойчивостью, особеннно когда матрица R плохо обусловлена. Будешь получать всякие exception' ы из-за того, что напрашивается решение с комплексными коэффициентами.
Положение осложняется тем, что для речи порядок LPC фильтра должен быть не ниже 12. Иногда и больше.
Вобщем, с наскока сразу не сделаешь, потратишь некоторое время. Зато в Матлабе получается всё красиво smile.gif

Автор: podval 2.6.2004, 13:09
Как пример - процедура Левинсона-Дарбина. Не самое лучшее решение, но наведет на мысли.

Код

#include <math.h>
#include <stdlib.h>
#include <stdio.h>

/*
Calculation of LPC filter koeffs using Levinson - Durbin recursion.

*acf = ponter to array of autocorrelation function values acf[0], acf[1]....acf[lpc_order]

*lpc = pointer to filter koeffs calculated by function  a[0],a[1]...a[lpc_order-1]

lpc_order = the order of LPC
*/

float lpc(float *acf, float *lpc, int lpc_order)
{

int i,j;
float tmp0,E,Pk;
float *tmp;

tmp=(float *)malloc(lpc_order*sizeof(float));

E=acf[0];
for(i=0;i<lpc_order;i++) lpc[i]=0.0;

for(i=0;i<lpc_order;i++)
{
tmp0=acf[i+1];
for(j=0;j<i;j++) tmp0-=lpc[j]*acf[i-j];

if(fabs(tmp0)>=E) break;

lpc[i]=Pk=tmp0/E;
E-=tmp0*Pk;
for(j=0;j<i;j++) tmp[j]=lpc[j];
for(j=0;j<i;j++) lpc[j]-=Pk*tmp[i-j-1];
}

free(tmp);

return E;
}

/*

LPC analyse FIR filter (whitening filter)

*data = pointer to input/output data
*lpc = pointer to filter koeffs
*z = pointer to filter memory

data_length = the length of the data to be processed
lpc_order = the order of LPC

*/

void lpc_analyse_filter(float *data,float *lpc,float *z,int data_length,int lpc_order)
{
int i,j;
float tmp;

for(i=0;i<data_length;i++)
{
tmp=data[i];
for(j=0;j<lpc_order;j++) tmp-=z[j]*lpc[j];
for(j=lpc_order-1;j>0;j--) z[j]=z[j-1];
z[0]=data[i];
data[i]=tmp;
}
return;
}

/*

LPC synthesis IIR filter (modeling filter)

*data = pointer to input/output data
*lpc = pointer to filter koeffs
*z = pointer to filter memory

data_length = the length of the data to be processed
lpc_order = the order of LPC

*/


void lpc_synthesis_filter(float *data,float *lpc,float *z,int data_length,int lpc_order)
{
int i,j;
float tmp;

for(i=0;i<data_length;i++)
{
tmp=data[i];
for(j=0;j<lpc_order;j++) tmp+=z[j]*lpc[j];
for(j=lpc_order-1;j>0;j--) z[j]=z[j-1];
z[0]=data[i]=tmp;
}
return;
}

Автор: maxim1000 2.6.2004, 17:38
Цитата
Как пример - процедура Левинсона-Дарбина. Не самое лучшее решение, но наведет на мысли.

упс... в моей магистерской как раз используется этот метод...
а нельзя ли подробней почему? (а то надо быть готовым к этому на защите smile.gif)

Автор: podval 3.6.2004, 21:08
А что тут говорить? Итеративная процедура, придуманная ого-го когда. На защите наверняка могут спросить об устойчивости синтезированного фильтра. Если фильтр неустойчив, то при малом входном сигнале можно получить очень большой выходной. Скажешь, как ввести проверку условия устойчивости.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)