void CALLBACK CWaveIn::waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch(uMsg) {
case MM_WIM_DATA:
WAVEHDR* pWaveHdr = ( (WAVEHDR*)dwParam1 );
                   FLOAT fValue=0;         
         
         dwSize=waveFmt.nBlockAlign; // 这里dwSize=2
for (DWORD i=0;i<pWaveHdr->dwBytesRecorded ;i++)
{
DWORD k=0;
for (DWORD j=0;j<dwSize;j++)
{
k|=(DWORD)pWaveHdr->lpData[i+j] << (j*8);
}
fValue+= (FLOAT) k;
}
原以为计算出的fValue就是音量大小,可事实并不是这样。
不向microphone说话时pWaveHdr->lpData指向的音频数据的值都很大(多数为0xfd90)
,当有的时候那些值又变得很小(多数为0x01df)。

}

解决方案 »

  1.   

    我对这个有些不解
    for (DWORD i=0;i<pWaveHdr->dwBytesRecorded ;i++)
    {
    DWORD k=0;
    for (DWORD j=0;j<dwSize;j++)
    {
    k|=(DWORD)pWaveHdr->lpData[i+j] << (j*8);
    }
    fValue+= (FLOAT) k;
    }
    不知你的采样格式是怎么的,几通道?样本位数?
    nBlockAlign = nChannels * wBitsPerSample /8;
    通过nBlockAlign并无法确定lpData数据排列是怎样的吧,可根据nChannels和wBitsPerSample这两个来确定lpData数据的排列。双通道和单通道,8位和16位采样精度的数据排列都不一样的。
      

  2.   

    dwSize=nBlockAlign
    dwSize=nChannels * (wBitsPerSample /8);
    根据MSDN所说的,这两个不就等值吗?
    那位高手能帮我解决,我高分相赠啊
      

  3.   

    呵呵
    1、你的提法有问题,音量大小怎么能够根据waveInProc中的数据来计算呢?!!!里面存储的仅仅是声音数据而已,音量大小是控制声卡和波形来得到的。
    2、然后再给你解释为什么lpData里面的值为什么会那么大:因为声音的字节可以8位,16位(甚至8的整数倍),字节数越大能包含的声音信息越精确。因此,从这个角度来说,怎么能直接加它们来得到音量呢?!!!
    3、你要计算平均音量大小,就先要知道声音的存储数据的字节数。你可以把所有的变换成8位来计算;这样就一样了。
    当然,你加完之后再换也可以。
    满意了吧?!
    ///////////////////////
    哎!打了这么多字,肚皮都饿了。
    :)
      

  4.   

    借题发挥
    我用了那么多的WAVE API,就是得不到声音数据,也播放不出来,求救。
      

  5.   

    呵呵,吃饭归来了!播放么?
    给你个最简单的吧:PlaySound("文件路径\\文件名");
      

  6.   

    我代码写错了
    应该为:
    dwSize=fmtWave.nBlockAlign;
    for (DWORD i=0; i<pWaveHdr->dwBytesRecorded / dwSize ;i++)
    {
    DWORD k=0;
    for (DWORD j=0;j<dwSize;j++)
    {
    k|=(DWORD)pWaveHdr->lpData[i*dwSize+j] << (j*8);
    }
    fValue+= (FLOAT) k;
    }
    请真正的高手帮帮忙啊
      

  7.   

    如果nChannels == 1的话,nBlockAlign的数据只有一个声道的数据,是可以的;但如果你的nChannels == 2,那么一个nBlockAlign就包含了左右声道的数据,照你这么计算,就把两声道的值都合在一起变成一个数了,这样就不行了。
    lpData格式: nChannels==2: 左声道|右声道|左声道|右声道....
    当wBitsPerSample==16时,每个声道的数据又是这样排列的: 高8位|低8位.....
      

  8.   

    不好意思,刚打错了,当wBitsPerSample==16时,每个声道的数据又是这样排列的: 低8位|高8位.....你的算法我看了,对单通道的是可以这么加的,但对双通道的就不行了。
      

  9.   

    不管它是单通道还是双通道,反正dwSize就是一个样本的大小
      

  10.   

    唉,真糟糕
    对双通道的来说,dwSize是两个通道的一次采样的值,就以8bit2channels的来说,一个样本数据是:
    左声道8位|右声道8位, 假设有个样本是0xaa|0xa0,本来是要分成两个通道分别加的,但被这么一移位,变成了0xa0aa,假设再有一个这样的样本,那就变成0xa0aa+0xa0aa了。但本来应该是左声道:0xaa+0xaa,右声道0xa0+0xa0的。 这两种计算方法会得到一样的结果吗?
      

  11.   

    就算是这样,但我的nChannel始终为1
      

  12.   

    大家分享一下:
    void CALLBACK CRecorderCtrlCtrl::GetWaveValue(LPBYTE lpWaveBuffer, DWORD dwWaveBufferLen,DWORD dwBitsPerSample,DWORD dwUserData)
    {
    CRecorderCtrlCtrl* pCtrl=(CRecorderCtrlCtrl*) (dwUserData);
    if (dwUserData!=0 && pCtrl->GetSafeHwnd() && dwBitsPerSample!=0)
    {

    CClientDC dc(pCtrl);
    CDC dcMem;
    dcMem.CreateCompatibleDC (&dc);
    CPen pen;
    CPen* pOldPen;
    static int nRed= (::GetTickCount ()+rand()) % 256 ;
    static int nGreen = (::GetTickCount ()+rand()) % 256 ;
    static int nBlue= (::GetTickCount ()+rand()) % 256 ;

    pen.CreatePen (PS_SOLID,1,RGB(nRed,nGreen,nBlue));
    pOldPen=dcMem.SelectObject(&pen);
    CRect rcClient;
    pCtrl->GetClientRect(&rcClient);

    CBitmap bitmap;
    CBitmap* pOldBitmap;

    bitmap.CreateCompatibleBitmap(&dc,rcClient.Width (),rcClient.Height ());
    pOldBitmap =(CBitmap*)dcMem.SelectObject(&bitmap);
    pCtrl->DrawBackgroundToDc(&dcMem);

    DWORD size;
    size = dwBitsPerSample == 16 ? dwWaveBufferLen/2 : dwWaveBufferLen;

    int yy = rcClient.Height()/2;
    dcMem.MoveTo (0,yy);
    int h=yy;

    BOOL bTalk=FALSE; // useless,remove it if it's unecessary
    short sample;
    int x,y;
    int oldx=0;
    for(int register i = 0 ; i <(long)size ; i++) //to draw first channel
    {
    sample = dwBitsPerSample == 16 ? ((*((short*)lpWaveBuffer+i))*h)/(65535/2) : ( (*((BYTE*)lpWaveBuffer+i)-128)*h)/128;
    x = int(((float)i/size)*(rcClient.Width()));
    y = yy-sample;
    if( abs(sample) > 15 && !bTalk )
    {
    bTalk = TRUE;
    }
    if (x!=oldx)
    {
    dcMem.LineTo (x,y);
    //static int nGreen=150;
    dcMem.SelectObject(pOldPen);
    pen.DeleteObject();
    pen.CreatePen (PS_SOLID,1,RGB(nRed++,nGreen++,nBlue++));
    if (nGreen>255)
    nGreen=50;
    if (nRed > 255)
    nRed=30;
    if (nBlue>255)
    nBlue=70;
    pOldPen=dcMem.SelectObject (&pen);
    oldx=x;
    }
    }

    //dc.StretchBlt(0,0,rcClient.Width (),rcClient.Height (),&dcMem,0,0,rcClient.Width ()
    // ,rcClient.Height(),SRCCOPY);
    dc.BitBlt (0,0,rcClient.Width (),rcClient.Height(),&dcMem,0,0,SRCCOPY);
    dcMem.SelectObject(pOldPen);
    }}