录制声音并且播放录取的声音

录制声音一般采用两种机制:

第一种: 直接在UI下采用消息;

第二种: 开辟一个线程单独进行;

下面先介绍第一种如何进行,DEMO是网上的,挺零碎的,我费了点功夫,调试能直接使用的.

<1> : wav族函数进行声音采集和播放时,会以下几个消息:

 MM_WIM_OPEN、 MM_WIM_DATA、MM_WIM_CLOSE、MM_WOM_OPEN、MM_WOM_DONE、MM_WOM_CLOSE

所以新建一个MFC工程,并且添加如下三个消息:

MM_WIM_OPEN、 MM_WIM_DATA、MM_WIM_CLOSE

当然也可以将另外三个播放的消息也一并添加.

假设新建了Recorde MFC Dialog工程.

<2> : 添加消息:

// Generated message map functions
 //{{AFX_MSG(CRecordeDlg)
 virtual BOOL OnInitDialog();
...
 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);
...
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()

BEGIN_MESSAGE_MAP(CRecordeDlg, CDialog)
 //{{AFX_MSG_MAP(CRecordeDlg)
...
 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)

...

 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

<3> : 添加头文件:

#include<mmsystem.h>
#pragma comment(lib, "Winmm.lib")

全局变量:

 

#define INP_BUFFER_SIZE 2048//该值越大,录取的数据就越多.
#define WAVE_HEADER_SIZE 44

 

enum et{
 RECORD_STATE_INIT,
 RECORD_STATE_STOP,
 RECORD_STATE_STOPING,
 RECORD_STATE_PLAYING,
 RECORD_STATE_RECING
};

类中自定义变量:

int m_nRecordState;

DWORD m_dwDataLength;        //数据长度
 WAVEFORMATEX m_waveform;    //声音格式
 HWAVEIN m_hWaveIn;            //音频输入句柄
 HWAVEOUT m_hWaveOut;        //音频输出句柄
 PBYTE m_pSaveBuffer;        //音频存储内存

 WAVEHDR m_WAVEHDR1;
 WAVEHDR m_WAVEHDR2;

 char m_cbBuffer1[INP_BUFFER_SIZE];    //声音临时缓存1
 char m_cbBuffer2[INP_BUFFER_SIZE];    //声音临时缓存2

新添加录音button1播放button2按钮.

<4> : 录音按钮如下:

void CRecordeDlg::OnButton1()
{
 // TODO: Add your control notification handler code here
 //打开声音设备
    if(waveInOpen(&m_hWaveIn,WAVE_MAPPER,&m_waveform,
            (DWORD)m_hWnd,NULL,CALLBACK_WINDOW)){
        MessageBeep(MB_ICONEXCLAMATION);
        MessageBox(_T("录制声音失败!"),
                    _T("错误"),MB_ICONEXCLAMATION|MB_OK);
        return;
    }

    //设置缓冲区
    m_WAVEHDR1.lpData = (LPTSTR)m_cbBuffer1;
    m_WAVEHDR1.dwBufferLength = INP_BUFFER_SIZE;
    m_WAVEHDR1.dwBytesRecorded = 0;
    m_WAVEHDR1.dwUser=0;
    m_WAVEHDR1.dwFlags=0;
    m_WAVEHDR1.dwLoops=1;
    m_WAVEHDR1.lpNext=NULL;
    m_WAVEHDR1.reserved=0;

    m_WAVEHDR2.lpData=(LPTSTR)m_cbBuffer2;
    m_WAVEHDR2.dwBufferLength = INP_BUFFER_SIZE;
    m_WAVEHDR2.dwBytesRecorded = 0;
    m_WAVEHDR2.dwUser=0;
    m_WAVEHDR2.dwFlags=0;
    m_WAVEHDR2.dwLoops=1;
    m_WAVEHDR2.lpNext=NULL;
    m_WAVEHDR2.reserved=0;

    //设置双缓冲
    waveInPrepareHeader(m_hWaveIn,&m_WAVEHDR1,sizeof(WAVEHDR));
    waveInPrepareHeader(m_hWaveIn,&m_WAVEHDR2,sizeof(WAVEHDR));

    waveInAddBuffer(m_hWaveIn,&m_WAVEHDR1,sizeof(WAVEHDR));
    waveInAddBuffer(m_hWaveIn,&m_WAVEHDR2,sizeof(WAVEHDR));

    //先随便分配个内存
    if(m_pSaveBuffer == NULL){
        free(m_pSaveBuffer);
        m_pSaveBuffer = NULL;
    }
    m_pSaveBuffer = (PBYTE)malloc(1);
    m_dwDataLength = 0;

    //开始录音
    // Begin sampling   
    waveInStart(m_hWaveIn);

}

播音按钮如下:

void CRecordeDlg::OnButton2()
{
 // TODO: Add your control notification handler code here
 //打开声音播放句柄
    if(waveOutOpen(&m_hWaveOut,WAVE_MAPPER,&m_waveform,(DWORD)m_hWnd, NULL, CALLBACK_WINDOW)){
        MessageBeep(MB_ICONEXCLAMATION);
        MessageBox(_T("录制声音失败!"),_T("错误"),MB_ICONEXCLAMATION|MB_OK);
        return;
    }
}

 

<4> :添加响应消息函数(附带了功能代码):

 

LRESULT CRecordeDlg::OnMM_WIM_CLOSE (UINT wParam,LONG lParam){

 

 waveInUnprepareHeader(m_hWaveIn, &m_WAVEHDR1, sizeof (WAVEHDR)) ;
    waveInUnprepareHeader(m_hWaveIn, &m_WAVEHDR2, sizeof (WAVEHDR)) ;
   
    m_nRecordState = RECORD_STATE_STOP;
    //SetButtonState();

 

    return NULL;
}

 

LRESULT CRecordeDlg::OnMM_WIM_DATA (UINT wParam,LONG lParam){

 

 PWAVEHDR pWaveHdr = (PWAVEHDR)lParam;
   
    if(pWaveHdr->dwBytesRecorded > 0){
        m_pSaveBuffer = (PBYTE)realloc(m_pSaveBuffer,m_dwDataLength + pWaveHdr->dwBytesRecorded);
        if(m_pSaveBuffer == NULL){
            waveInClose (m_hWaveIn);
            MessageBeep (MB_ICONEXCLAMATION) ;
            AfxMessageBox("erro memory");
            return NULL;
        }

 

        memcpy(m_pSaveBuffer+m_dwDataLength , pWaveHdr->lpData,pWaveHdr->dwBytesRecorded);

 

        m_dwDataLength += pWaveHdr->dwBytesRecorded;
    }

 

    if(m_nRecordState == RECORD_STATE_STOPING){
        waveInClose(m_hWaveIn);       
    }

 

    waveInAddBuffer(m_hWaveIn, pWaveHdr, sizeof (WAVEHDR));

 

    return NULL;
}

 

LRESULT CRecordeDlg::OnMM_WIM_OPEN (UINT wParam,LONG lParam){

 

 m_nRecordState = RECORD_STATE_RECING;
    //SetButtonState();
    return NULL;
}

 

LRESULT CRecordeDlg::OnMM_WOM_CLOSE (UINT wParam,LONG lParam){

 

 m_nRecordState = RECORD_STATE_STOP;
    //SetButtonState();
    return NULL;
}

 

LRESULT CRecordeDlg::OnMM_WOM_DONE (UINT wParam,LONG lParam){

 

 PWAVEHDR pWaveHdr = (PWAVEHDR)lParam;
    waveOutUnprepareHeader (m_hWaveOut, pWaveHdr, sizeof (WAVEHDR)) ;
    waveOutClose (m_hWaveOut);
    return NULL;
}

 

LRESULT CRecordeDlg::OnMM_WOM_OPEN  (UINT wParam,LONG lParam){

 

 memset(&m_WAVEHDR1,0,sizeof(WAVEHDR));
    m_WAVEHDR1.lpData = (char *)m_pSaveBuffer;//指向要播放的内存
    m_WAVEHDR1.dwBufferLength = m_dwDataLength;//播放的长度
    m_WAVEHDR1.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    m_WAVEHDR1.dwLoops = 1;

 

    waveOutPrepareHeader(m_hWaveOut,&m_WAVEHDR1,sizeof(WAVEHDR));

 

    waveOutWrite(m_hWaveOut,&m_WAVEHDR1,sizeof(WAVEHDR));

 

    m_nRecordState = RECORD_STATE_PLAYING;
    //SetButtonState();
    return NULL;
}

 

 

转载于:https://www.cnblogs.com/MMLoveMeMM/articles/3110610.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值