錄音機程序

 工程在這裏:http://download.csdn.net/detail/aihahaheihei/3835562

目的是寫一個既可以錄音又可以錄視頻的,現在先分開寫錄音的和錄視頻的,接下來就把兩者結合起來啦

這個工程裏面的有些東西沒有描述出來了,下面的文章是轉來的,但工程是我自己寫的,多加了的東東,呵呵,要學會站在巨人的肩膀上創作。

祝自己好運^_^

/*語音採集 - WINDOWS API*/

#define INP_BUFFER_SIZE (8 * 1024) //定義緩衝區大小
bool m_record,m_play;    //m_record表示是否正在錄音,m_play表示是否正在回放

WAVEFORMATEX waveform;    //WAV文件頭包含音頻格式
DWORD dwDataLength,dwRepetitions; //dwDataLength已有的數據長度,dwRepetitions重複次數
HWAVEIN hWaveIn;     //輸入設備句柄
HWAVEOUT hWaveOut;     //輸出設備句柄
PBYTE pBuffer1,pBuffer2;   //保存輸入數據的兩個緩衝區。
         //如果只要一個緩衝區,當緩衝區滿,保存數據時,會無法保存這段時間採集的語音,導致最後獲得的聲音斷斷續續。
         //使用兩個緩衝區,當一個緩衝區滿的時候,保存這個已滿的緩衝區數據,而由另一個緩衝區繼續採集語音。
PBYTE pSaveBuffer,pNewBuffer;  //保存數據的內存地址。
PWAVEHDR pWaveHdr1,pWaveHdr2;  //聲音文件頭

afx_msg LRESULT OnMM_WIM_OPEN(UINT wParam,LONG lParam);
afx_msg LRESULT OnMM_WIM_DATA(UINT wParam,LONG lParam);
afx_msg LRESULT OnMM_WIM_CLOSE(UINT wParam,LONG lParam);
afx_msg LRESULT OnMM_WOM_OPEN(UINT wParam,LONG lParam);
afx_msg LRESULT OnMM_WOM_DONE(UINT wParam,LONG lParam);
afx_msg LRESULT OnMM_WOM_CLOSE(UINT wParam,LONG lParam);  //聲明幾個回調函數


pWaveHdr1=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR)));
pWaveHdr2=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR))); //給聲音文件頭分配內存空間
pSaveBuffer = reinterpret_cast<PBYTE>(malloc(1));    //給數據內存地址分配空間

 

//消息綁定

BEGIN_MESSAGE_MAP(/*窗口類*/, /*窗口類的父類*/)
 ON_MESSAGE(MM_WIM_OPEN,OnMM_WIM_OPEN)
 ON_MESSAGE(MM_WIM_DATA,OnMM_WIM_DATA)
 ON_MESSAGE(MM_WIM_CLOSE,OnMM_WIM_CLOSE)
 ON_MESSAGE(MM_WOM_OPEN,OnMM_WOM_OPEN)
 ON_MESSAGE(MM_WOM_DONE,OnMM_WOM_DONE)
 ON_MESSAGE(MM_WOM_CLOSE,OnMM_WOM_CLOSE)

END_MESSAGE_MAP()

 

void RecordStart()     //錄音準備
{
  m_record=true;
  pBuffer1=(PBYTE)malloc(INP_BUFFER_SIZE);
  pBuffer2=(PBYTE)malloc(INP_BUFFER_SIZE);    //給緩衝區分配空間
  if (!pBuffer1||!pBuffer2)
  {
   if (pBuffer1) free(pBuffer1);
   if (pBuffer2) free(pBuffer2);
   MessageBeep(MB_ICONEXCLAMATION);
   AfxMessageBox(L"Memory error!");
   return ;
  }
  
  //設置錄音方式
  waveform.wFormatTag  = WAVE_FORMAT_PCM;   //PCM編碼
  waveform.nChannels  = 1;       //單聲道
  waveform.nSamplesPerSec = 16000;      //採樣頻率,每秒採集次數
  waveform.nAvgBytesPerSec= waveform.nSamplesPerSec * sizeof(unsigned short); 
  waveform.nBlockAlign = waveform.nChannels * waveform.wBitsPerSample / 8;
  waveform.wBitsPerSample = 16;       //採樣位,模擬信號轉數字信號的精準度
  waveform.cbSize   = 0;       //PCM編碼時,此處爲0
  
  if (waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW)) { //打開輸入設備
   free(pBuffer1);
   free(pBuffer2);
   MessageBeep(MB_ICONEXCLAMATION);
   AfxMessageBox(L"Audio can not be open!");
  }
  //初始化聲音文件頭
  pWaveHdr1->lpData=(LPSTR)pBuffer1;   //設置緩衝區
  pWaveHdr1->dwBufferLength=INP_BUFFER_SIZE; //緩衝區大小
  pWaveHdr1->dwBytesRecorded=0;
  pWaveHdr1->dwUser=0;
  pWaveHdr1->dwFlags=0;
  pWaveHdr1->dwLoops=1;
  pWaveHdr1->lpNext=NULL;
  pWaveHdr1->reserved=0;
  waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));  //將緩衝區信息和輸入設備關聯
  waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ; //將緩衝區地址添加到輸入設備中
   
  pWaveHdr2->lpData=(LPSTR)pBuffer2;
  pWaveHdr2->dwBufferLength=INP_BUFFER_SIZE;
  pWaveHdr2->dwBytesRecorded=0;
  pWaveHdr2->dwUser=0;
  pWaveHdr2->dwFlags=0;
  pWaveHdr2->dwLoops=1;
  pWaveHdr2->lpNext=NULL;
  pWaveHdr2->reserved=0;
  waveInPrepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));
  waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ; //同上
  
  pSaveBuffer = (PBYTE)realloc (pSaveBuffer, 1) ;
  dwDataLength = 0 ;
  waveInStart (hWaveIn) ; //打開輸入設備,開始錄音
}
void RecordStop()
{
  m_record=false;
  waveInReset(hWaveIn); //停止錄音,關閉輸入設備
}
void PlayStart()
{
if (waveOutOpen(&hWaveOut,WAVE_MAPPER,&waveform,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW)) //打開輸出設備,開始回放
 {
  MessageBeep(MB_ICONEXCLAMATION);
  AfxMessageBox(L"Audio output error");
 }
 m_play=true;
}
void PlayStop()
{
  waveOutReset(hWaveOut);  //停止回放,關閉輸出設備
  m_play = false;
}
LRESULT OnMM_WIM_OPEN(UINT wParam, LONG lParam) //開始錄音
{
 // TODO: Add your message handler code here and/or call default
 m_record=TRUE;
 TRACE(L"MM_WIM_OPEN\n");
 return 0;
}

LRESULT ChelloWMDlg::OnMM_WIM_DATA(UINT wParam, LONG lParam) //緩衝區滿的時候,對應的聲音文件頭如pWaveHdr1作爲lParam傳遞進來
{
 // TODO: Add your message handler code here and/or call default
 // Reallocate save buffer memory
 
 pNewBuffer = (PBYTE)realloc (pSaveBuffer, dwDataLength +
  ((PWAVEHDR) lParam)->dwBytesRecorded) ; 
 
 if (pNewBuffer == NULL)
 {
  waveInClose (hWaveIn) ;
  MessageBeep (MB_ICONEXCLAMATION) ;
  AfxMessageBox(L"error memory");
  return 0;
 }
 
 pSaveBuffer = pNewBuffer ;  //在pSaveBuffer尾部繼續申請空間(上面的realloc 函數)
 //////////////////////////////////////////////////////////////////////////
 
 CopyMemory(pSaveBuffer + dwDataLength, ((PWAVEHDR) lParam)->lpData,
  ((PWAVEHDR) lParam)->dwBytesRecorded) ; //將緩衝區數據((PWAVEHDR) lParam)->lpData複製到pSaveBuffer的尾部剛申請的空間中
 
 dwDataLength += ((PWAVEHDR) lParam)->dwBytesRecorded ;//加長pSaveBuffer的實際數據長度
 
 if (m_record==false)
 {
  waveInClose (hWaveIn) ;//停止錄音,關閉輸入設備
  return 0;
 }
  
 //將音頻寫入到文件中
 FILE* fp=fopen("ecord.pcm","ab+");
 if(fp==NULL)
 {
  printf("fopen error,%d",__LINE__);
 }
 fwrite(((PWAVEHDR) lParam)->lpData,((PWAVEHDR) lParam)->dwBytesRecorded,1,fp);
 fclose(fp);
 
 // Send out a new buffer
 waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;//將緩衝區添加回到設備中
 //假如現在是pWaveHdr1滿了,lParam就是pWaveHdr1,在我們保存pWaveHdr1的數據時,pWaveHdr2正在錄音,保存完pWaveHdr1,再把pWaveHdr1添加回到設備中,這樣達到兩個緩衝區交替使用。
 TRACE(L"done input data\n");
 return 0;

 
}

LRESULT ChelloWMDlg::OnMM_WIM_CLOSE(UINT wParam, LONG lParam) //停止錄音時
{
 // TODO: Add your message handler code here and/or call default
 TRACE(L"MM_WIM_CLOSE\n");

 if (0==dwDataLength) {   //沒有數據,長度爲0
  return 0;
 }
 waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;//取消輸入設備和pWaveHdr1的關聯
 waveInUnprepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
 
 m_record = FALSE ;
 
 free (pBuffer1) ;
 free (pBuffer2) ;
 
 if (dwDataLength > 0)
 {
  //enable play
 }
 return 0;
}

LRESULT ChelloWMDlg::OnMM_WOM_OPEN(UINT wParam, LONG lParam)//開始回放
{
 TRACE(L"open MM_WOM_OPEN\n");
 // Set up header
 
 pWaveHdr1->lpData          = (LPSTR)pSaveBuffer ;
 pWaveHdr1->dwBufferLength  = dwDataLength ;
 pWaveHdr1->dwBytesRecorded = 0 ;
 pWaveHdr1->dwUser          = 0 ;
 pWaveHdr1->dwFlags         = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
 pWaveHdr1->dwLoops         = dwRepetitions ;
 pWaveHdr1->lpNext          = NULL ;
 pWaveHdr1->reserved        = 0 ;
 
 // Prepare and write
 
 waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
 waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;

 m_play = TRUE ;
  
 return 0;
}

LRESULT ChelloWMDlg::OnMM_WOM_DONE(UINT wParam, LONG lParam){ //回放完畢

 TRACE(L"open MM_WOM_DONE\n");
 waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
 waveOutClose (hWaveOut) ;
 
 dwRepetitions = 1 ;
 m_play = FALSE ; 
 
 return  0;
 
}
LRESULT ChelloWMDlg::OnMM_WOM_CLOSE(UINT wParam, LONG lParam){ //關閉回放
 TRACE(L"open MM_WOM_CLOSE\n");
 dwRepetitions = 1 ;
 m_play = FALSE ; 

 return 0;
}

發佈了75 篇原創文章 · 獲贊 14 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章