wave (引自周长发)

BOOL CWaveManagerDoc::RecordWave()
{
    // 查询系统是否安装有波形音频输入设备
    if (waveInGetNumDevs() == 0)
    {
        // 系统没有波形音频输入设备
        return FALSE;
    }

    m_nBlockAlign = m_nChannels*m_wBitsPerSample/8;
    m_dwBufferSize = m_nSamplesPerSec*m_nBlockAlign;

    // 设置录音格式
    m_Format.wFormatTag = WAVE_FORMAT_PCM;
    m_Format.nChannels  = m_nChannels;
    m_Format.nSamplesPerSec = m_nSamplesPerSec;
    m_Format.nAvgBytesPerSec = m_nSamplesPerSec*m_nBlockAlign;
    m_Format.nBlockAlign = m_nBlockAlign;
    m_Format.wBitsPerSample = m_wBitsPerSample;
    m_Format.cbSize = sizeof(WAVEFORMATEX);

    // 打开波形音频设备
    if (MMSYSERR_NOERROR !=
                waveInOpen(&m_hWaveIn, WAVE_MAPPER, &m_Format,
                        (UINT)GetView()->m_hWnd, 0L, CALLBACK_WINDOW))
    {
        // 打开波形音频设备出错
        return FALSE;
    }

    // 给第一缓冲区及波形数据头WAVEHDR分配、锁定全局内存
    m_lpWaveHdr1 = (LPWAVEHDR)GlobalAllocPtr(
                            GMEM_MOVEABLE | GMEM_SHARE,
                            (DWORD) sizeof(WAVEHDR));
    if (!m_lpWaveHdr1)
    {
        //分配全局内存出错
        return FALSE;
    }
    m_lpBuffer1 = (LPSTR)GlobalAllocPtr(
                            GMEM_MOVEABLE | GMEM_SHARE,
                            m_dwBufferSize);
    if (!m_lpBuffer1)
    {
        //分配全局内存出错
        FreeGlobalPtr( m_lpWaveHdr1 );
        return FALSE;
    }

    // 准备第一数据缓冲区,并送入设备
    m_lpWaveHdr1->lpData = m_lpBuffer1;
    m_lpWaveHdr1->dwBufferLength = m_dwBufferSize;
    m_lpWaveHdr1->dwBytesRecorded = 0L;
    m_lpWaveHdr1->dwUser = 0L;
    m_lpWaveHdr1->dwFlags = 0L;
    m_lpWaveHdr1->dwLoops = 1L;
    m_lpWaveHdr1->lpNext = NULL;
    m_lpWaveHdr1->reserved=0L;
    if(MMSYSERR_NOERROR !=
                waveInPrepareHeader(m_hWaveIn,
                    m_lpWaveHdr1, sizeof(WAVEHDR)))
    {
        // 准备WAVEHDR结构数据出错
        FreeGlobalPtr( m_lpWaveHdr1 );
        FreeGlobalPtr( m_lpBuffer1 );
        return FALSE;
    }
    waveInAddBuffer(m_hWaveIn, m_lpWaveHdr1, sizeof(WAVEHDR));

    // 给第二缓冲区及波形数据头WAVEHDR分配、锁定全局内存
    m_lpWaveHdr2 = (LPWAVEHDR)GlobalAllocPtr(
                            GMEM_MOVEABLE | GMEM_SHARE,
                            (DWORD) sizeof(WAVEHDR));
    if (!m_lpWaveHdr2)
    {
        //分配全局内存出错
        FreeGlobalPtr( m_lpWaveHdr1 );
        FreeGlobalPtr( m_lpBuffer1 );
        return FALSE;
    }
    m_lpBuffer2 = (LPSTR)GlobalAllocPtr(
                            GMEM_MOVEABLE | GMEM_SHARE,
                            m_dwBufferSize);
    if (!m_lpBuffer2)
    {
        //分配全局内存出错
        FreeGlobalPtr( m_lpWaveHdr1 );
        FreeGlobalPtr( m_lpBuffer1 );
        FreeGlobalPtr( m_lpWaveHdr2 );
        return FALSE;
    }

    // 准备第二数据缓冲区,并送入设备
    m_lpWaveHdr2->lpData = m_lpBuffer2;
    m_lpWaveHdr2->dwBufferLength = m_dwBufferSize;
    m_lpWaveHdr2->dwBytesRecorded = 0L;
    m_lpWaveHdr2->dwUser = 0L;
    m_lpWaveHdr2->dwFlags = 0L;
    m_lpWaveHdr2->dwLoops = 1L;
    m_lpWaveHdr2->lpNext = NULL;
    m_lpWaveHdr2->reserved=0L;
    if(MMSYSERR_NOERROR !=
                waveInPrepareHeader(m_hWaveIn,
                        m_lpWaveHdr2, sizeof(WAVEHDR)))
    {
        // 准备WAVEHDR结构数据出错
        FreeGlobalPtr( m_lpWaveHdr1 );
        FreeGlobalPtr( m_lpBuffer1 );
        FreeGlobalPtr( m_lpWaveHdr2 );
        FreeGlobalPtr( m_lpBuffer2 );
        return FALSE;
    }
    waveInAddBuffer(m_hWaveIn, m_lpWaveHdr2, sizeof(WAVEHDR));

    // 为波形音频数据预先分配内存,初始大小为1字节
    FreeGlobalPtr( m_lpData );
    m_lpData = (HPSTR)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, 1);

    // 开始录音
    m_dwDataLength = 0L;
    waveInStart(m_hWaveIn);

    return TRUE;
}

/********************************************************/

void CWaveManagerDoc::WimData(LPARAM lParam)
{
    // 获取消息参数
    LPWAVEHDR pWaveHdr = (LPWAVEHDR)lParam;
    HPSTR pBuffer = pWaveHdr->lpData;
   
    // 重新分配内存大小
    m_lpData = (HPSTR)GlobalReAllocPtr(m_lpData,
                            pWaveHdr->dwBytesRecorded+m_dwDataLength,
                            GMEM_MOVEABLE | GMEM_SHARE);
    if (! m_lpData)
    {
        // 重新分配内存大小出错
        waveInClose(m_hWaveIn);
        return;
    }

    // 将新录制的数据加道数据块中
    ::CopyMemory((HPSTR)(m_lpData+m_dwDataLength),
                 pBuffer,
                 (UINT)(pWaveHdr->dwBytesRecorded));
   
    // 更新数据块大小
    m_dwDataLength += pWaveHdr->dwBytesRecorded;

    // 将缓冲区重新送入设备
    pWaveHdr->dwBufferLength  = m_dwBufferSize;
    pWaveHdr->dwBytesRecorded = 0L;
    pWaveHdr->dwFlags = 0L;
    waveInAddBuffer(m_hWaveIn, pWaveHdr, sizeof(WAVEHDR));
}

/********************************************************/

BOOL CWaveManagerDoc::WriteWaveFile(LPCTSTR lpszFileName)
{
   HMMIO          hmmio;
   MMCKINFO       mmckinfoParent;
   MMCKINFO       mmckinfoSubchunk;

   // 打开文件,使用缓冲区输入/输出
   if(!(hmmio = mmioOpen((LPSTR)lpszFileName, NULL,
                    MMIO_CREATE | MMIO_WRITE | MMIO_ALLOCBUF)))
   {
        // 打开文件出错
        return FALSE;
   }

    // Create the output file RIFF chunk of form type 'WAVE'.
    mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
    if (MMSYSERR_NOERROR !=
            mmioCreateChunk(hmmio, &mmckinfoParent, MMIO_CREATERIFF))
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }
   
    //We are now descended into the 'RIFF' chunk we just created.
    //Now create the 'fmt ' chunk. Since we know the size of this chunk,
    //specify it in the MMCKINFO structure so MMIO doesn't have to seek
    //back and set the chunk size after ascending from the chunk.
    mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
    mmckinfoSubchunk.cksize = sizeof(m_Format);  // we know the size of this ck.
    if (MMSYSERR_NOERROR !=
            mmioCreateChunk(hmmio, &mmckinfoSubchunk, 0))
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }
 
    // Write the WAVEFORMATX structure to the 'fmt ' chunk.
    if (mmioWrite(hmmio, (HPSTR) &m_Format, sizeof(m_Format))
                != sizeof(m_Format))
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }

    // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
    if (MMSYSERR_NOERROR !=
            mmioAscend(hmmio, &mmckinfoSubchunk, 0))
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }


    // Create the 'data' chunk that holds the waveform samples.
    mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
    if (MMSYSERR_NOERROR !=
            mmioCreateChunk(hmmio, &mmckinfoSubchunk, 0))
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }
   
    if (mmioWrite(hmmio, m_lpData, m_dwDataLength)
                    != (LONG)m_dwDataLength)
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }
   
    if (MMSYSERR_NOERROR !=
            mmioAscend(hmmio, &mmckinfoSubchunk, 0))
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }

    // Ascend the output file out of the 'RIFF' chunk -- this will cause
    // the chunk size of the 'RIFF' chunk to be written.
    // We are done -- files are closed below.
    mmckinfoParent.cksize=m_dwDataLength + sizeof(WAVEFORMATEX);
    if (MMSYSERR_NOERROR !=
            mmioAscend(hmmio, &mmckinfoParent, 0))
    {
        mmioClose(hmmio, 0);
        return FALSE;
    }

    // 文件已使用完毕,关闭它
    mmioClose(hmmio, 0);

    return TRUE;
}

/********************************************************/

void CWaveManagerView::OnDraw(CDC* pDC)
{
    CWaveManagerDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    if (! pDoc->m_dwSampleNum || ! pDoc->m_dwDataLength)
        return;

    CRect rc;
    GetClientRect(&rc);
    int nWidth = rc.Width();
    int nHeight = rc.Height();

    float fYUnit;
    float fXUnit = (float)nWidth/(float)pDoc->m_dwSampleNum;
    CPen pen(PS_SOLID, 1, RGB(0,0,0));
    CPen *pOldPen = pDC->SelectObject(&pen);
    if (pDoc->m_Format.wBitsPerSample == 8)
        fYUnit = (float)((float)nHeight/255.0);
    else if (pDoc->m_Format.wBitsPerSample == 16)
        fYUnit = (float)((float)nHeight/65535.0);
           
    int      i, j, k, x, y;
    y = (int)((float)pDoc->m_lpDrawValue[0]*fYUnit);
    pDC->MoveTo(0, y);
    for (x=1; x<nWidth; x++)
    {
        j = (int)((float)(x-1)/fXUnit);
        i = (int)((float)x/fXUnit);
        for (k=j; k<i; k+=(i-j)/10)
        {
            y = (int)((float)pDoc->m_lpDrawValue[k]*fYUnit);
            pDC->MoveTo(x, y);
            pDC->LineTo(x, nHeight-y);
        }
      }

    pDC->SelectObject(pOldPen);
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值