现在做一个小项目,要求将背景音乐和自己录入的声音合并为一个.wav保存,没这方面的经验和知识,望大家给点意见,谢先!

解决方案 »

  1.   

    背景音乐和自己录入的声音合并为一个.wav保存这种合并可不是一般的wav文件衔接合并,而是混音问题
    这方面的api函数我也用的不灵活,不过directsound在这方面应该功能强大一些
    具体细节,就希望楼主多查阅这方面的资料了
      

  2.   

    在MSDN中是如下介绍的,
    Creating the DirectSound Object
    The simplest way to create the DirectSound object is with the DirectSoundCreate function. The first parameter of this function specifies the GUID of the device to be associated with the object. You can obtain this GUID by Enumeration of Sound Devices, or you can simply pass NULL to create the object for the default device. LPDIRECTSOUND lpDirectSound; 
    HRESULT       hr;
    hr = DirectSoundCreate(NULL, &lpDirectSound, NULL));
     
    The function returns an error if there is no sound device or if the sound device is being used by the waveform-audio (non-DirectSound) functions. You should prepare your applications for this call to fail so that they can either continue without sound or prompt the user to close the application that is already using the sound device.You can also create the DirectSound object by using the CoCreateInstance function, as follows: Initialize COM at the start of your application by calling CoInitialize and specifying NULL.
    if (FAILED(CoInitialize(NULL)))
        return FALSE;
     
    Create your DirectSound object by using CoCreateInstance and the IDirectSound::Initialize method, rather than the DirectSoundCreate function.
    dsrval = CoCreateInstance(&CLSID_DirectSound,
                              NULL, 
                              CLSCTX_INPROC_SERVER,
                              &IID_IDirectSound,
                              &lpds);
        if (SUCCEEDED(dsrval))
            dsrval = IDirectSound_Initialize(lpds, NULL);
     
    CLSID_DirectSound is the class identifier of the DirectSound driver object class and IID_IDirectSound is the DirectSound interface that you should use. The lpds parameter is the uninitialized object CoCreateInstance returns.Before you use a DirectSound object created with the CoCreateInstance function, you must call the IDirectSound::Initialize method. This method takes the driver GUID parameter that DirectSoundCreate typically uses (NULL in this case). After the DirectSound object is initialized, you can use and release the DirectSound object as if it had been created by using the DirectSoundCreate function.Before you close the application, shut down COM by calling the CoUninitialize function, as follows:CoUninitialize(); 
     
     
      

  3.   

    使用多通道。
    将不同声音源的声音加载到不同的缓冲区中然后在一个合成缓冲区里面混合;如果立即播放这个缓冲区即可听到效果,如果你想输出成wav文件,就把这个合成缓冲区里面的数据写成wav文件。不过还有一个直接写成wav文件的办法,惭愧的是本人也正在找这方面的资料,虽然知道要用多通道写,但具体怎么写进去还在探索。汗......
      

  4.   

    如果需要的只是把两个WAV文件混音,那要怎么样做?
    上面说的那些方法只是知道了大概的方向,最好能给出例子。
      

  5.   

    我好像在一本书上见过着个问题,是铁道出版社的<<vc多媒体编程>>,可以参考一下
      

  6.   

    你们在讨论啥呢?不是用“录音机”就可以了吗?开始 => 所有程序 => 附件 => 娱乐 => 录音机 => 编辑 => 插入文件 ...

    开始 => 所有程序 => 附件 => 娱乐 => 录音机 => 编辑 => 与文件混音 ...搞这么麻烦做啥呢?
      

  7.   

    实时地混音,就是将多路Wave数据进行相互叠加处理到另一个目的缓冲区,最终将该目的的缓冲区提交给Wave输出设备。
    将每一路Wave数据作为一个单独通道,分别从每个通道取一数据片段,把取得的几个数据片段相互叠加,然后存进另外一个目的缓冲区中。为了便于处理,缓冲区通常采用数组的形式存放Wave数据。
        如果话音数据,采用采样频率1025Hz,8位单声道的数据格式,那么一秒的话音数据量为11025个字节。
        为了达到实时的效果,目的缓冲区通常都设置比较小,大约可存放1/8秒的话音数据量,对于前述的话音格式,目的缓冲区的大小为11025/8=1375个字节。
        下面具体看一下Wave数据以数组形式存放时的混音过程。如图2所示。
              Wave1          
                                        +
              Wave2
                                        +
              Wave3          
                                        +
              Waven          
                                         =
             目的缓冲区      
                           D〔i〕=W1〔i〕+W2〔i〕+W3〔i〕+Wn〔i〕
                             图2  多路Wave数据的叠加过程
        假设有4路Wave数据,目的缓冲区的大小为1378,混音子函数调用为                                  Mixer(lpDest,rgpCDdata,4,1378)。
        下面给出混音子函数的实现。其中lpDest为目的缓冲区,rgWaveSrc为多路Wave数据源,iNumWaves为Wave数据源的通道数,wLen为目的缓冲区长度。
    Void mixit(LPSAMPLE lpDest,LPSAMPLE rgWaveSrc[],intiNumWaves,WORDwLen)
    {
        int,,iSum;
        WORD ctr;

        ctr=0
        While(wLen)
        {
           iSum=128;/*静音时数值为128*/
           for(I=0;I<iNumWaves;I++)
           iSum=iSum+*(rgWaveSrc[]+ctr)-128;
           PEG(int)0,iSum,(int)225);/*对转换结果处理*/
           *lpDest++=iSum;
           ctr++;
           wLen--;
         }
    }注意一点的是对于单声道数据一个字节表示一个采样值,采样值在0—255之间,各个通道的对应Wave数据相加后,就会溢出,还需要将相加结果转换成0—255之间的数值。
        将该目的缓冲区中的Wave数据经WaveOutWrite函数输出,就能同时听到四个不同的声音,当Wave输出设备播放完目的缓冲区中的数据便返回,请求用户提供更多的Wave输出数据,因为Wave输出设备只能输出提交给它的Wave数据;另外,对Wave数据进行混音还需要一定的时间,因此当提交一个目的缓冲区中的数据给Wave输出设备后,就必须马上混叠另一段Wave数据来提交给Wave输出设备,作为下一个输出的数据缓冲区,避免声音输出的中断,后一个目的缓冲区提交后被输出设备放入输出队列中,当第一个目的缓冲区中输出完毕后再输出它的数据,当输出设备在输出第二个目的缓冲区的数据时,又能将第三段数据混合进第一个目的缓冲区中,然后重新提交,直到提交完所有的Wave数据,那时就将停止输出。在实际应用中目的缓冲区的数要多个,一般为3至4个,图3给出了混音、提交的完整过程
      

  8.   

    楼主说的太多了,让人家看的头都大了,有点自己的东西嘛?看不惯呀!
    告诉你一个简单的:
    用绘声绘影把两个.wav文件都导进去,然后选导出声音文件,就OK了
      

  9.   

    应该先搞清楚wave文件的格式,他的声道规范是比较简单的,因此对于一般的合并还是不难做的。
      

  10.   

    to  shakira008(我是新手学习中) :
    先谢,还有吗?
      

  11.   

    VOID FillBuffer (INS ins, PBYTE pBuffer, int iNumSamples)
    {
          static double  dAngle [MAX_PARTIALS] ;
          double         dAmp, dFrq, dComp, dFrac ;
          int            i, iPrt, iMsecTime, iCompMaxAmp, iMaxAmp, iSmp ;
               // Calculate the composite maximum amplitude
         
          iCompMaxAmp = 0 ;
          for (iPrt = 0 ; iPrt < ins.iNumPartials ; iPrt++)
          {
               iMaxAmp = 0 ;
               for (i = 0 ; i < ins.pprt[iPrt].iNumAmp ; i++)
                    iMaxAmp = max (iMaxAmp, ins.pprt[iPrt].pEnvAmp[i].iValue) ;
               iCompMaxAmp += iMaxAmp ;
    }
         
               // Loop through each sample
          for (iSmp = 0 ; iSmp < iNumSamples ; iSmp++)
          {
               dComp = 0 ;
               iMsecTime = (int) (1000 * iSmp / SAMPLE_RATE) ;
              
                    // Loop through each partial
               for (iPrt = 0 ; iPrt < ins.iNumPartials ; iPrt++)
               {
                    dAmp = 0 ;
                    dFrq = 0 ;
                   
                    for (i = 0 ; i < ins.pprt[iPrt].iNumAmp - 1 ; i++)
                    {
               if (iMsecTime >= ins.pprt[iPrt].pEnvAmp[i  ].iTime &&
               iMsecTime <= ins.pprt[iPrt].pEnvAmp[i+1].iTime)
                         {
               dFrac = (double) (iMsecTime -
               ins.pprt[iPrt].pEnvAmp[i  ].iTime) /
               (ins.pprt[iPrt].pEnvAmp[i+1].iTime -
               ins.pprt[iPrt].pEnvAmp[i  ].iTime) ;
                             
               dAmp = dFrac  * ins.pprt[iPrt].pEnvAmp[i+1].iValue +
               (1-dFrac) * ins.pprt[iPrt].pEnvAmp[i  ].iValue ;
               break ;
               }
               }
                   
               for (i = 0 ; i < ins.pprt[iPrt].iNumFrq - 1 ; i++)
               {
              if (iMsecTime >= ins.pprt[iPrt].pEnvFrq[i  ].iTime &&
                  iMsecTime <= ins.pprt[iPrt].pEnvFrq[i+1].iTime)
               {
                  dFrac = (double) (iMsecTime -ins.pprt[iPrt].pEnvFrq[i  ].iTime) /
                                   (ins.pprt[iPrt].pEnvFrq[i+1].iTime -
                                   ins.pprt[iPrt].pEnvFrq[i  ].iTime) ;
                  dFrq = dFrac  * ins.pprt[iPrt].pEnvFrq[i+1].iValue + (1-dFrac) * 
    ins.pprt[iPrt].pEnvFrq[i  ].iValue ;
                break ;
                  }
                  }
                 dComp += dAmp * SineGenerator (dFrq, dAngle + iPrt) ;
               }
               pBuffer[iSmp] = (BYTE) (127 + 127 * dComp / iCompMaxAmp) ;
          }
    }