两个PCM音频内容,要求混音!
我现在的做法是直接将Wave值相加除二,这显然是不对的!
求教一种恰当的方法:
能给出代码的我将重谢!
任何相关内容提供都将被加分

解决方案 »

  1.   

    假设有4路Wave数据,目的缓冲区的大小为1378,混音子函数调用为                                  Mixer(lpDest,rgpCDdata,4,1378)。
        下面给出混音子函数的实现。其中lpDest为目的缓冲区,rgWaveSrc为多路Wave数据源,iNumWaves为Wave数据源的通道数,wLen为目的缓冲区长度。
    Void mixit(LPSAMPLE lpDest,LPSAMPLE rgWaveSrc[],int iNumWaves,WORD wLen)
    {
        int,,iSum;
        WORD ctr;
        ctr=0
        While(wLen)
        {
           iSum=128;/*静音时数值为128*/
           for(I=0;I<iNumWaves;I++=
            iSum=iSum+*(rgWaveSrc[I]+ctr)-128;
           PEG((int)0,iSum,(int)225);/*对转换结果处理*/
           *lpDest++=iSum;
           ctr++;
           wLen--;
         }
    }注意一点的是对于单声道数据一个字节表示一个采样值,采样值在0—255之间,各个通道的对应Wave数据相加后,就会溢出,还需要将相加结果转换成0—255之间的数值。
      

  2.   

    class CWaveMix  
    {
    public:
    void MixData(PBYTE lpWaveSrc[],PBYTE lpWavDst,int iChannels,WORD wLen);
    CWaveMix();
    virtual ~CWaveMix();
    int Open(char*); //打开一个WAV文件
    int Play(HWND); //播放一个WAV文件
    int Add(char*); //往正在播放的WAV设备中添加WAV                                       文件
    int Stop(); //停止播放
    int Close(); //关闭设备
    int Continue();

    DWORD DataSize;
    WAVDATA* lpData;
    private:
    BOOL  OpenFlage;
    HGLOBAL hData;
    DWORD DataSize_start; PCMWAVEFORMAT  pFormat;
    WAVEHDR WaveHead;
    HWAVEOUT  hWaveOut; int m_Channels;
    };CWaveMix::CWaveMix()
    {
    memset(this,0,sizeof(CWaveMix));
    }CWaveMix::~CWaveMix()
    {
    Close();
    }int CWaveMix::Open(char* name)
    {
    HMMIO  hMmio;
    MMCKINFO pinfo;
    MMCKINFO cinfo; if(hMmio)
    Close(); //打开WAV文件,返回一个HMMIO句柄
    hMmio=mmioOpen(name,NULL,MMIO_READ);
    if(!hMmio)
    return FALSE;
    OpenFlage=1; //查找父块"wave";
    pinfo.fccType=mmioFOURCC('W','A','V','E');
    if(mmioDescend(hMmio,&pinfo,NULL,MMIO_FINDRIFF))
    goto FALSE_END; //查找子块"fmt"  parent"riff";
    cinfo.ckid=mmioFOURCC('f','m','t',' ');
    if(mmioDescend(hMmio,&cinfo,&pinfo,MMIO_FINDCHUNK))
             goto FALSE_END; mmioRead(hMmio,(LPSTR)&pFormat,sizeof(PCMWAVEFORMAT));//cinfo.cksize);
    if(pFormat.wf.wFormatTag!=WAVE_FORMAT_PCM)
             goto FALSE_END; //跳入块"FMT"
    mmioAscend(hMmio,&cinfo,0); //查找数据块
    cinfo.ckid=mmioFOURCC('d','a','t','a');
    if(mmioDescend(hMmio,&cinfo,&pinfo,MMIO_FINDCHUNK))
             goto FALSE_END;
    DataSize=cinfo.cksize;
    //读取数据
    hData=GlobalAlloc(GMEM_MOVEABLE 
                         | GMEM_SHARE,DataSize);
    lpData=(WAVDATA*)GlobalLock(hData);
    if( !hData || !lpData ) goto FALSE_END;
    if(mmioRead(hMmio,(HPSTR)lpData,DataSize)!=(LRESULT)DataSize)
             goto FALSE_END; //close and return
    mmioClose(hMmio,MMIO_FHOPEN);
    return TRUE;FALSE_END:
    if(hMmio)mmioClose(hMmio,MMIO_FHOPEN);
    if(lpData)LocalUnlock(hData);
    if(hData)GlobalFree(hData);
    memset(this,0,sizeof(CWaveMix));
    return 0;
    }int CWaveMix::Play(HWND hP)
    {
    if(!OpenFlage)
    return FALSE; //检测系统播放功能
    if(waveOutOpen(NULL,WAVE_MAPPER,(WAVEFORMATEX*)&pFormat,NULL,NULL,WAVE_FORMAT_QUERY))
            return Close(); if(waveOutOpen(&hWaveOut,WAVE_MAPPER,(WAVEFORMATEX*)&pFormat,(DWORD)hP,0,CALLBACK_WINDOW))
            return Close(); WaveHead.lpData=(LPSTR)lpData;
    WaveHead.dwBufferLength=DataSize;
    WaveHead.dwFlags=0L;
    WaveHead.dwLoops=0L;
    DataSize_start=DataSize; //往WAV设备中添加数据
    if(waveOutPrepareHeader(hWaveOut,&WaveHead, sizeof(WAVEHDR)))
           return Close(); if(waveOutWrite(hWaveOut,&WaveHead,sizeof(WAVEHDR)))
           return Close(); return TRUE;
    }int CWaveMix::Continue()
    {
    CWaveMix wav;
    if(!wav.Open("2.wav"))
    return FALSE;
    memcpy(lpData,wav.lpData,DataSize);
    // WaveHead.lpData=(LPSTR)wav.lpData;
    // WaveHead.dwBufferLength=wav.DataSize;
    if(waveOutPrepareHeader(hWaveOut,&WaveHead, sizeof(WAVEHDR)))
           return Close();
    if(waveOutWrite(hWaveOut,&WaveHead,sizeof(WAVEHDR)))
           return Close();
    return TRUE;
    }//#define min(a, b)  (((a) < (b)) ? (a) : (b))
    int CWaveMix::Add(char* name)
    {
    register int x;
    if(!OpenFlage)
    return Open(name); CWaveMix wav;
    if(!wav.Open(name))
    return FALSE; MMTIME time;
    //获得WAV文件当前播放位置
    time.wType=TIME_BYTES;
    if(waveOutGetPosition(hWaveOut,&time,sizeof(MMTIME)))
    time.u.cb=0;
    DWORD start=((time.u.cb>>1)<<1);
    DWORD end=min(DataSize_start,wav.DataSize);
    // DWORD end=wav.DataSize;
    register WAVDATA* lpd=lpData+start;
    for(register DWORD i=0;i<end;i++)
    {
    //将两组WAV文件数据相加,并检测数据大小是否合法,如果
    //数据大小越界,则分别取最大值和最小值
    x=(((*(lpd+i))+(*(wav.lpData+i))))-128;
    if(x<0)
    x=0;
       if(x>255)
    x=255;
    *(lpd+i)=(BYTE)(x);
    }
    return TRUE;
    }int CWaveMix::Stop()
    {
    return !waveOutReset(hWaveOut);
    }int CWaveMix::Close()
    {
    if(hWaveOut)
    {
    waveOutReset(hWaveOut);
    waveOutUnprepareHeader(hWaveOut,&WaveHead,sizeof(WAVEHDR));
    waveOutClose(hWaveOut);
    }
    if(lpData)LocalUnlock(hData);
    if(hData)GlobalFree(hData);
    memset(this,0,sizeof(CWaveMix));
    return 0;
    }
    void CWaveMix::MixData(PBYTE lpWavSrc[], PBYTE lpWavDst, int iChannels, WORD wLen)
    {
    int i,iSum;
    for(int j=0;j<wLen;j++)
    {
    iSum=128;//静音时数值为128
    for(i=0;i<iChannels;i++)
    iSum=iSum+*(lpWavSrc[i]+j)-128;
    if(iSum<0) iSum=0;
    if(iSum>255) iSum=255;
    *lpWavDst++=iSum;
    }
    }
      

  3.   

    简单的混音就是相加除二如果你要考虑两个声音的距离等其它因素,DirectSound有这个功能