在windows 下有一個 winAPI library 可以實現錄音的功能
API 說明可以參考 MSDN 網站:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743833(v=vs.85).aspx
這裡主要是介紹如何將電腦麥克風的聲音錄起來,
並存成 wav 檔
1.Audio 結構
在聲音的格式中,定義在 WAVEFORMATEX 這個結構中:
typedef struct {
WORD wFormatTag; //audio format,這裡使用WAVE_FORMAT_PCM
WORD nChannels; //1為單聲道,2為雙聲道
DWORD nSamplesPerSec; //每秒採集的聲音sample數量
DWORD nAvgBytesPerSec; //每秒傳送byte數量
WORD nBlockAlign; //nBlockAlign = (nChannels*wBitsPerSample)/8;
WORD wBitsPerSample; //每個sample儲存多少bit的資料,一般為8bit or 16bit
WORD cbSize; //額外資訊的大小,通常是non-PCM時,才會用到,這裡設0
} WAVEFORMATEX;
聲音的採集資料,定義在 WAVEHDR 這個結構中:
typedef struct {
LPSTR lpData; //buffer的資料
DWORD dwBufferLength; //buffer的長度
DWORD dwBytesRecorded; //buffer的資料大小(bytes)
DWORD dwUser; //通常為0
DWORD dwFlags; //描述額外的資料
DWORD dwLoops; //在播放的時候使用
struct wavehdr_tag* lpNext;//應該給link list用
DWORD reserved; //保留
} WAVEHDR;
2.使用API
使用windows API錄音 主要利用到下面函式:
waveInOpen() //開啟錄音裝置 waveInPrepareHeader() //buffer header 準備 waveInAddBuffer() //輸入buffer waveInStart() //開始錄音 waveInStop() //停止錄音 waveInUnprepareHeader() //buffer header 清空 waveInClose() //關閉錄音裝置
3.code ( 含儲存成wav檔 )
#include "stdafx.h"
#include "windows.h"
#pragma comment(lib, "winmm.lib") //windows API library for wave
#define DATASIZE 22050*2*5 //SamplesPerSec * byte per sample * duration time
int _tmain(int argc, _TCHAR* argv[])
{
HWAVEIN audio_in;
WAVEFORMATEX audio_format; //structure of wave format
WAVEHDR audio_header;
int log;
char* soundBuffer[DATASIZE];
audio_format.wFormatTag=WAVE_FORMAT_PCM;
audio_format.nChannels=1;
audio_format.nSamplesPerSec=22050;
audio_format.wBitsPerSample=16;
audio_format.cbSize=0;
audio_format.nBlockAlign = (audio_format.nChannels * audio_format.wBitsPerSample)/8;
audio_format.nAvgBytesPerSec = (audio_format.nSamplesPerSec*audio_format.nBlockAlign);
log = waveInOpen(&audio_in,WAVE_MAPPER,&audio_format,NULL,NULL,NULL);
//open input device
if (log == MMSYSERR_NOERROR)
printf("waveInOpen success\n");
else
printf("waveInOpen fail\n");
audio_header.dwFlags=0;
audio_header.dwUser=0;
audio_header.dwLoops=0;
audio_header.dwBytesRecorded=0;
audio_header.lpData = (LPSTR)soundBuffer;
audio_header.dwBufferLength = DATASIZE;
//prepare buffer header
log = waveInPrepareHeader( audio_in, &audio_header, sizeof(WAVEHDR) );
if (log == MMSYSERR_NOERROR)
printf("waveInPrepareHeader success\n");
else
printf("waveInPrepareHeader fail\n");
//send buffer to input device
log = waveInAddBuffer( audio_in, &audio_header, sizeof(WAVEHDR) );
if (log == MMSYSERR_NOERROR)
printf("waveInAddBuffer success\n");
else
printf("waveInAddBuffer fail\n");
if (! waveInStart(audio_in) ) //start recording
printf("recording start for 5 sec...\nenter any char to stop\n");
else
printf("recording fail...\n");
getchar();
if (! waveInStop(audio_in) ) //stop recording
printf("recording stop\n");
else
printf("recording stop fail\n");
//clean buffer header
if(waveInUnprepareHeader(audio_in, &audio_header, sizeof(WAVEHDR)))
printf("UnPrepare Header fail\n");
else
printf("UnPrepare Header success\n");
Sleep(500);
if (waveInClose(audio_in)==MMSYSERR_NOERROR)
printf("waveInClose success\n");
else
printf("waveInClose fail\n");
//saving as wave file
MMCKINFO wav_file_header1;
MMCKINFO wav_file_header2;
HMMIO wav_file;
MMRESULT result;
long wav_log;
//create wav file
wav_file = mmioOpen(L"wavfile.wav",NULL,MMIO_CREATE|MMIO_WRITE|MMIO_EXCLUSIVE | MMIO_ALLOCBUF);
if(wav_file == NULL)
printf("mmioOpen fail\n");
ZeroMemory(&wav_file_header1, sizeof(MMCKINFO));
wav_file_header1.fccType=mmioFOURCC('W', 'A', 'V', 'E');
result = mmioCreateChunk(wav_file ,&wav_file_header1, MMIO_CREATERIFF); //create RIFF chunk
if (result==MMSYSERR_NOERROR)
printf("mmioCreateChunk: wav_file_header1 %s ok\n",result);
else
printf("mmioCreateChunk: wav_file_header1 fail\n");
ZeroMemory(&wav_file_header2, sizeof(MMCKINFO));
wav_file_header2.ckid=mmioFOURCC('f', 'm', 't', ' ');
wav_file_header2.cksize=sizeof(WAVEFORMATEX)+audio_format.cbSize;
//create fmt chunk
result = mmioCreateChunk(wav_file ,&wav_file_header2, 0);
if (result==MMSYSERR_NOERROR)
printf("mmioCreateChunk wav_file_header2 %s ok\n",result);
else
printf("mmioCreateChunk wav_file_header2 fail\n");
//輸入fmt chunk的data
wav_log = mmioWrite(wav_file ,(char*)&audio_format,sizeof(WAVEFORMATEX)+audio_format.cbSize);
if(wav_log==-1)
printf( "mmioWrite audio_format fail\n");
else
printf( "mmioWrite write %d bytes\n",wav_log);
//跳出fmt chunk
result = mmioAscend(wav_file,&wav_file_header2,0);
if (result==MMSYSERR_NOERROR )
printf( "mmioAscend wav_file_header2 %s ok\n",result);
else
printf( "mmioAscend wav_file_header2 %s fail\n",result);
wav_file_header2.ckid=mmioFOURCC('d', 'a', 't', 'a');
//create data Chunk
result = mmioCreateChunk(wav_file ,&wav_file_header2,0);
if (result==MMSYSERR_NOERROR)
printf( "mmioCreateChunk wav_file_header2 %s ok\n",result);
else
printf( "mmioCreateChunk wav_file_header2 %s fail\n",result);
printf("audio_header %d BytesRecorded\n",audio_header.dwBytesRecorded);
//輸入audio data
wav_log = mmioWrite(wav_file,(char*)audio_header.lpData,DATASIZE);
if(wav_log==-1)
printf( "mmioWrite audio data fail\n");
else
printf( "mmioWrite success : write %d bytes\n",wav_log);
//跳出data chunk
result = mmioAscend(wav_file,&wav_file_header2,0);
if (result==MMSYSERR_NOERROR)
printf( "mmioAscend wav_file_header2 %s ok\n",result);
else
printf( "mmioAscend wav_file_header2 %s fail\n",result);
//跳出RIFF chunk
result = mmioAscend(wav_file,&wav_file_header1,0);
if (result==MMSYSERR_NOERROR)
printf( "mmioAscend wav_file_header1 %s ok\n",result);
else
printf( "mmioAscend wav_file_header1 %s fail\n",result);
result = mmioClose(wav_file,0); //close the wav file
if (result==MMIOERR_CANNOTWRITE){
printf( "mmioClose fail\n");
}
return 0;
}
可以看到儲存下來的wav檔










































