因为要搞一些声音处理的算法,本来在matlab下调试,虽然matlab很强大,但是要完全按照自己的意志去仿真一些东西的时候还是有点问题,不是matlab办不到,主要是找不到一些合适的模块,或者写一个S-functuon太麻烦了,还是在自己用程序实现比较实际,而且算法也可以比较快的移植到DSP上面。
Widnows下声音输入输出有一系列的API函数,我这里给出的例子是读取一个Wav文件,然后输出到声卡,不要看小看这段看像根本没有的代码,他是声音处理的基本输入输出函数,在这之上,你可以加上IIR,FIR滤波,频谱分析等等。如果你像我一样想偷懒,拿来就用,可以下载Wave_effec的VC程序,在VC6下通过。 注意Wave文件缺省是c:\test.wav. 只能是48K,16bit,单通道的Wave文件
本来我是一个Frame一个frame这样来处理,不过不知道是什么原因,windows播放的时候会断断续续,所以一次处理完才输出。
在processing函数中,可以加上你想要的任意处理。
void Processing( char * p, char *q,unsigned long n)
{
short *in,*out;
unsigned int i;
in=(short *)p;out=(short *)q;
for(i=0;i<n/2;i++)
{
// fprintf(wavform,"%d\n",*in );
*out++=(short) (*in++) ;
}
}
在我的程序中有一个wav_form的文件,是用来写数据到一个文件中,到matlab中分析用的,你可以不用它。如果你想用它,下面的函数可能对你有用,wavread,wavwrite,wavplay,load(用来load 数据到matlab中)
主程序如下
void CALLBACK
waveOutProc( HWAVEOUT hwo,
UINT uMsg,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2 )
{
printf( "Get a waveOutProc uMsg = %d\n", uMsg );
if (uMsg == WOM_DONE)
{
PostThreadMessage( CurThreadID, WM_QUIT , 11, 22 ); // WM_QUIT
}
return ;
}
int main(int argc, char* argv[])
{
HWAVEOUT phwo;
CurThreadID = GetCurrentThreadId( ); // 取得当前线程的 ID (标识号)
//fp=fopen(argv[1] ,"rb");
fp=fopen("c:\\test.wav" ,"rb");
wavform=fopen("wav_form.dat","wt");
if(fp==NULL || wavform ==NULL)
{
printf("Can not find file\n");
return 0;
}
fseek(fp,0x14,SEEK_SET);
fread(&waveformat,sizeof(waveformat),1,fp);
printf("This porgram is only for 1 channel 16bit Wave file!\n");
printf("wFormatTag: %d\n",waveformat.wFormatTag );
printf("Channel: %d\n",waveformat.nChannels );
printf("nSamplesPerSec: %d\n",waveformat.nSamplesPerSec );
printf("nAvgBytesPerSec: %d\n",waveformat.nAvgBytesPerSec );
printf("nBlockAlign: %d\n",waveformat.nBlockAlign );
printf("wBitsPerSample: %d\n",waveformat.wBitsPerSample );
printf("cbSize: %d\n",waveformat.cbSize );
fseek(fp,0x28,SEEK_SET);
fread(&filesize,4,1,fp);
printf("WAVE Data Size: %d\n",filesize);
/*
waveformat.wFormatTag=WAVE_FORMAT_PCM;
waveformat.nChannels=1;
waveformat.nSamplesPerSec=0; //8000;
waveformat.nAvgBytesPerSec=0; //8000;
waveformat.nBlockAlign=0; //1;
waveformat.wBitsPerSample=0; //8; //指定录音格式
waveformat.cbSize=0;
*/
if (waveOutGetNumDevs())
{
;// printf("有可以使用的 WaveOut 通道\n");
}
else
{
printf("没有可以使用的 waveOut 通道\n");
return 0;
}
int res=waveOutOpen( &phwo, WAVE_MAPPER, &waveformat,(DWORD)waveOutProc , NULL, CALLBACK_FUNCTION ); //打开录音设备
if ( res == MMSYSERR_NOERROR )
{
;//printf("打开 waveOut 成功\n"); // 验证创建是否成功
}
else
{
printf("打开 waveOut 失败,Error_Code = %d\n", res );
}
m_pWaveHdr1.lpData = (char *)GlobalLock( GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, datasize) );
m_pWaveHdr2.lpData = (char *)GlobalLock( GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, filesize) );
memset(m_pWaveHdr1.lpData, 0, datasize );
memset(m_pWaveHdr2.lpData, 0, datasize );
char *prt=m_pWaveHdr2.lpData;
// 读入磁盘数据
fseek(fp,46,SEEK_SET);
unsigned int frame=0;
buf_id=1;
buf_count=1;
for(int i=0;i < filesize / datasize;i++)
{
fread(m_pWaveHdr1.lpData, datasize, 1, fp);
buf_count++;
Processing(m_pWaveHdr1.lpData,prt,datasize);
prt+=datasize;
}
printf("processing frame done\n");
m_pWaveHdr1.dwBufferLength = datasize;
m_pWaveHdr1.dwBytesRecorded = 0;
m_pWaveHdr1.dwUser = 0;
m_pWaveHdr1.dwFlags = 0;
m_pWaveHdr1.dwLoops = 0;
m_pWaveHdr2.dwBufferLength = filesize;
m_pWaveHdr2.dwBytesRecorded = 0;
m_pWaveHdr2.dwUser = 0;
m_pWaveHdr2.dwFlags = 0;
m_pWaveHdr2.dwLoops = 0;
UINT resPrepare = 0;
resPrepare = waveOutPrepareHeader( phwo, &m_pWaveHdr2, sizeof(WAVEHDR) );
if ( resPrepare == MMSYSERR_NOERROR)
{
;//printf("准备放音用头文件成功");
}
else
{
printf( "不能开辟放音头文件,Error_Code = %d\n", resPrepare );
return 0;
}
if (waveOutPause(phwo) )
;///printf("无法 Pause");
else
;//printf("成功 Pause");
if ( waveOutWrite( phwo, &m_pWaveHdr2, sizeof(WAVEHDR) ) )
;// printf("开始写入放音数据失败");
else
;//printf("开始写入放音数据成功");
if ( waveOutRestart(phwo) )
;//printf(" 非法 Resume");
else
;//printf(" Resume 到 Playback");
PostThreadMessage( CurThreadID, WM_USER , 11, 22 ); // WM_QUIT
// 进入消息循环
MSG msg;
while(1)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
printf( "Get The uMsg =%d\n", msg.message );
if (msg.message == WM_QUIT)
break;
}
else
{
;//printf("没有取到消息");
WaitMessage();
}
} // end while
if ( waveOutPause(phwo) )
;//printf("无法 Pause");
else
;//printf("成功 Pause");
if ( waveOutReset(phwo) )
;//printf("不能 Reset");
else
;//printf("成功 Reset");
// resPrepare = waveOutUnprepareHeader( phwo, &m_pWaveHdr1, sizeof(WAVEHDR) );
resPrepare = waveOutUnprepareHeader( phwo, &m_pWaveHdr2, sizeof(WAVEHDR) );
if ( resPrepare == MMSYSERR_NOERROR)
;//printf("释放放音用头文件成功");
else
printf( "不能释放放音头文件,Error_Code =%d", resPrepare );
if ( m_pWaveHdr1.lpData )
if ( GlobalFree(GlobalHandle( m_pWaveHdr1.lpData )) )
printf("Global Free 失败");
else
;// printf("Global Free 成功");
if ( m_pWaveHdr2.lpData )
if ( GlobalFree(GlobalHandle( m_pWaveHdr2.lpData )) )
printf("Global Free 失败");
else
;//printf("Global Free 成功");
if (res == MMSYSERR_NOERROR ) //关闭录音设备
if (waveOutClose(phwo)==MMSYSERR_NOERROR)
printf("正常关闭放音设备");
else
printf("非正常关闭放音设备");
fclose(wavform);
fclose(fp);
return 0;
}
我的程序主要改自csdn上的某位作者的程序,在此感谢他(她)。