#include "type.h"
#include "board.h"
#include "codec.h"
#include "mcbsp54.h"
#include "flash.h"
#include "stdio.h"
#include "tms320.h"
#include "math.h"
#include "dsplib.h"
#include "stdlib.h"
#define VOICELEN 8000
#define SHIFT 128
#define WINDOW 256
#define WEISHU 12
#define CEPBUFFERLEN 12*8
#define MAXREAL 100000000000.0
#pragma DATA_SECTION (jf,"audio_buffer")
DATA jf[WINDOW];
void tezheng(DATA *fan);
void checkstart(); //测试语音输入开始的子程序
void recvoice();
void train();
float dtw(DATA *cep,DATA *rcep); //语音是别的子程序
u16 min(u16 a,u16 b,u16 c);//求整形数最小值的子程序
float lmin(float a,float b,float c);//求浮点数最小值的子程序
HANDLE hHandset;
s16 data[VOICELEN];//存放输入的语音数据
DATA tempdata[WINDOW];//存放经过加窗后的语音数据
int begin=0; //语音开始录入的标志位
int end=0; //语音识别结束的帧数
int start=0; //语音识别开始的帧数
//int t=3;
unsigned int num_frame=0;
u16 dest=0x8000;
int checkresult=-535;
void main()
{
u16 i=0;
u16 j=0;
int t=0;//
float hamming[WINDOW];
DATA fan[CEPBUFFERLEN];
for(i=1;i<WINDOW+1;i++)
{
hamming[i]=0.54-0.46*cos(2*i*3.14159/(WINDOW-1));
}
if (brd_init(100))
return;
/* Open Handset Codec */
hHandset = codec_open(HANDSET_CODEC);
/* Set codec parameters */
codec_dac_mode(hHandset, CODEC_DAC_15BIT); /* DAC in 15-bit mode */
codec_adc_mode(hHandset, CODEC_ADC_15BIT); /* ADC in 15-bit mode */
codec_ain_gain(hHandset, CODEC_AIN_6dB); /* 6dB gain on analog input to ADC */
codec_aout_gain(hHandset, CODEC_AOUT_MINUS_6dB); /* -6dB gain on analog output from DAC */
codec_sample_rate(hHandset,SR_8000);
while(1){
while(t==4){};
i=1;
while (i<VOICELEN+1)
{
/* Wait for sample from handset */
while (!MCBSP_RRDY(HANDSET_CODEC)) {};
/* Read sample from and write back to handset codec */
data[i] = *(volatile u16*)DRR1_ADDR(HANDSET_CODEC);//语音的读入,将其存放到data数组中
i++;
}
i=1;
while (i<VOICELEN+1)
{
/* Wait for sample from handset */
while (!MCBSP_XRDY(HANDSET_CODEC)) {};
/* Read sample from and write back to handset codec */
*(volatile u16*)DXR1_ADDR(HANDSET_CODEC) = data[i];//语音的输出,将其从耳机端口输出
i++;
}
checkstart();
fan[0]=num_frame;//帧的长度
printf("%d\n",start);//打印从哪帧开始
printf("%d\n",end);//打印从哪帧结束
printf("%d\n",end-start); //打印帧的长度
for(i=start-1;i<end-1;i=i+SHIFT)//对每一帧进行处理
{
for(j=1;j<WINDOW+1;j++)
{
tempdata[j]=data[i+j]*hamming[j]; //将每一帧的数据进行汉明加窗处理
}
tezheng(&fan[(i+1-start)/SHIFT*WEISHU+1]); //求每一帧的特征值,存放到fan数组中
}
train(fan); //进入建立模板函数
if(t==3)
{
recvoice();//进入声音的识别函数
}
num_frame=0;
t++;
}
}
void checkstart()
{
int i,j,m=0,z[SHIFT],zero[VOICELEN/SHIFT]={0};
float en=0,pn=0;
float shorten,shortpn;
for(i=0;i<VOICELEN;i++)
{
en=en+abs(data[i]);//计算输入语音的总幅值
}
pn=en/VOICELEN;//计算输入语音的平均幅值
/*printf("%f\n",pn);*/
for(i=SHIFT;i<VOICELEN;i=i+SHIFT)//处理每一帧的数据
{
shorten=0;
shortpn=0;
for(j=0;j<SHIFT;j++)
{
shorten=shorten+abs(data[i+j]);//计算每一帧幅值的总和
z[j]=0.5*(data[j+i+1]/abs(data[j+i+1])-data[j+i]/abs(data[j+i]));//过零率的计算,data[m]取符号数减去data[m-1]取符号数,计算过过零点的数量
zero[m]=zero[m]+z[j];//将过零点的个数相加,送到zero数组中
if(j==SHIFT-1)
{
m++;//一帧的数据取完后,将m加一,进行下一帧的运算
}
}
shortpn=shorten/SHIFT;//将平均幅值放到shortpn中
/*printf("%f\n",shortpn);*/
if((shortpn*2>pn)||(zero[m+1]>3*zero[m]))//如果幅值和过零点均满足条件,则认为语音已经开始录入
{
start=i;//将开始的帧的数值送到start中
begin=1;
}
if((begin==1)&&(shortpn*4<pn))//满足语音录入结束的条件么
{
end=i;//满足,将结束时帧的数值送到end中
break;//跳出程序
}
}
if(begin==0) //语音一直没有开始
{
printf("voice never started!");
exit(0);//程序正常退出
}
if(end==0)
{
printf("voice does not end when buffer is full,it's too long");
exit(0);//程序正常退出
}
begin=0;//将begin归零
num_frame=(end-start)/SHIFT;//计算帧的个数,将其赋值给num_frame
/*printf("%d\n",num_frame);*/
}
void tezheng(DATA *fan)
{
int i,j,k,m=1;
float ff[13],jj[WINDOW],te[WEISHU]={0};
for(j=1;j<WINDOW+1;j++)
{
jf[j]=tempdata[j];//将加窗后的一帧的每一个值送到jf数组中
/*printf("%d\n",jf[j]);*/
}
cbrev(jf,jf,WINDOW/2);/* 求倒序 */
rfft(jf,WINDOW,1);//进行傅里叶变换
for(i=1;i<WINDOW+1;i=i+2)
{
jj[m]=sqrt(jf[i]*jf[i]+jf[i+1]*jf[i+1]); //将傅里叶变换系数存到jj数组中
m++;
}
for(j=1;j<=14;j++)
{
ff[j]=1960*(j+0.53)/(26.28-j);
//ff数组中的数据为118.6234177 204.2339374 297.1993127 398.5098743
}
for(j=1;j<WEISHU+1;j++)
{
for(k=WINDOW*ff[j]/8000+1;k<=WINDOW*ff[j+1]/8000;k++)
{//j=1时,k的取值范围是4.8~7.5
te[j]=te[j]+jj[k];
}
}
for(i=1;i<=WEISHU;i++)
fan[i]=te[i];//将每一维特征系数存放到fan数组中
}
void train(DATA *fan)
{
int i;
FILE *fp;
char filename[3];
ltoa(t,filename); //将t转换为字符型存放到filename数组中
fp=fopen(filename,"w");//建立以filename为文件名的文件,将fp指针指向该文件
for(i=1;i<num_frame*12+1;i++)
{
fprintf(fp,"%d",fan[i]); //将所有帧的特征值写入fp指向的文件中
fprintf(fp,"\n");
}
fclose(fp);
/* printf("shuo hua!\n");*/
}
void recvoice()
{
DATA cep[CEPBUFFERLEN]={0}; // cep数组的长度为12*8
DATA rcep0[CEPBUFFERLEN]={0};
DATA rcep1[CEPBUFFERLEN]={0};
DATA rcep2[CEPBUFFERLEN]={0};
int j;
float dist[3];
FILE *fp;
fp=fopen("0","r"); //打开文件名为0的文件,将fp指向它
for(j=1;j<CEPBUFFERLEN+1;j++)
{
fscanf(fp,"%d",&rcep0[j]);//将文件名为0的文件文件输出到rcep0数组中,即将“1”的特征矢量输出到rcep0数组中
}
fclose(fp);
fp=fopen("1","r");//打开文件名为1的文件,将fp指向它
for(j=1;j<CEPBUFFERLEN+1;j++)
{
fscanf(fp,"%d",&rcep1[j]);//将文件名为1的文件文件输出到rcep1数组中,即将“2”的特征矢量输出到rcep1数组中
}
fclose(fp);
fp=fopen("2","r");//打开文件名为2的文件,将fp指向它
for(j=1;j<CEPBUFFERLEN+1;j++)
{
fscanf(fp,"%d",&rcep2[j]);//将文件名为2的文件文件输出到rcep2数组中,即将“3”的特征矢量输出到rcep2数组中
}
fclose(fp);
fp=fopen("3","r");//打开文件名为3的文件,将fp指向它
for(j=1;j<CEPBUFFERLEN+1;j++)
{
fscanf(fp,"%d",&cep[j]);//将文件名为3的文件文件输出到rcep2数组中,即将再次输入的数据的特征矢量输出到rcep3数组中
}
fclose(fp);
/*printf("%d\n",PMST);*/
printf("Start recognizing!!\n");
printf("\n");
dist[0]=dtw(cep,rcep0); //利用dtw实现语音的识别
printf("%f\n",dist[0]);
dist[1]=dtw(cep,rcep1);
printf("%f\n",dist[1]);
dist[2]=dtw(cep,rcep2);
printf("%f\n",dist[2]);
for(checkresult=0;checkresult<3;checkresult++)
{
if(dist[checkresult]==lmin(dist[0],dist[1],dist[2]))
break;//找到最小的差别,将其付给checkresult
}
if(checkresult==0)
{printf("1\n");}//若checkresult=0,说明输入与第一个字匹配,即输出“1”
if(checkresult==1)//若checkresult=1,说明输入与第二个字匹配,即输出“2”