因开发需要,急需混音器的资料或源代码!
要求如下:
(1)能对实时的音频Buffer进行混音。
(2)至少支持8路。
有提供有用资料或代码者,重分酬谢!!!

解决方案 »

  1.   

    http://www.codeproject.com/audio/ADMixer.asp
      

  2.   

    ftp://pub:[email protected]/../源代码交换/freebird/MixWave.zip
      

  3.   

    ftp://pub:[email protected]/../源代码交换/freebird/MixWave.zip
      

  4.   

    我记得以前在一家公司做网络游戏时,看到DirectX和Direct Media,Direct Show有这方面的内容。关于音频方面的内容DirectX里面肯定有。
      

  5.   

    ftp://pub:[email protected]/上不去呀!
      

  6.   

    http://www.codeproject.com/audio/ADMixer.asp
      

  7.   

    用mci就自己混,用dx,建立soundbuffer就行。
      

  8.   

    我的来了用DIRECTSOUND,先把声音缓冲区的对象,读取WAV文件,及音量控制放在这个类里。
    先给类,看看:
    // DSBuffer.h : Definition of CDSBuffer class
    //#if !defined(AFX_DSBUFFER_H__7517D749_96E3_11D2_BBF3_9EB4940D843C__INCLUDED_)
    #define AFX_DSBUFFER_H__7517D749_96E3_11D2_BBF3_9EB4940D843C__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000#include <mmsystem.h>
    #include <dsound.h>//设置如下两个全局变量控制音量:
    extern int   m_nBkGrdVolume; //用于控制背景音乐音量大小
    extern int   m_nYinXiaoVolume; //用于控制音效音量大小//wav文件头格式
    struct WaveHeader
    {
    BYTE        RIFF[4];          // "RIFF"
    DWORD       dwSize;           // Size of data to follow
    BYTE        WAVE[4];          // "WAVE"
    BYTE        fmt_[4];          // "fmt "
    DWORD       dw16;             // 16
    WORD        wOne_0;           // 1
    WORD        wChnls;           // Number of Channels
    DWORD       dwSRate;          // Sample Rate
    DWORD       BytesPerSec;      // Sample Rate
    WORD        wBlkAlign;        // 1
    WORD        BitsPerSample;    // Sample size
    BYTE        DATA[4];          // "DATA"
    DWORD       dwDSize;          // Number of Samples
    };class CDSBuffer : public CObject
    {
    // Attribute
    protected:
    LPDIRECTSOUNDBUFFER m_lpDSBuffer; // 声音缓冲区对象public:
    CDSBuffer();
    CDSBuffer(const char* FileName,BOOL m_bBackGroundMusic,LPDIRECTSOUND lpDS,DWORD dwFlags = DSBCAPS_CTRLVOLUME );
    ~CDSBuffer();public:
    BOOL PlaySound(BOOL bContinue=FALSE);     //播放声音
    BOOL StopSound();  //停止播放
    BOOL CreateSoundBuffer(LPDIRECTSOUND lpDS, DWORD dwFlags, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo);
    BOOL ReadData(FILE* pFile, DWORD dwSize, DWORD dwPos);
    BOOL IsValid();
    LPDIRECTSOUNDBUFFER GetBuffer() { return m_lpDSBuffer;}
    void SetVolume(int percent=50);   //设置音量
    void VolumeDown(int percent=10);  //音量增大(percent为百分数,范围为
    void VolumeUp(int percent=10);    //音量减小  1~100) 

    private:
    BOOL    m_bBkGrdMusic;            //是否是背景音乐,TRUE为是
    };
    #endif // !defined(AFX_DSBUFFER_H__7517D749_96E3_11D2_BBF3_9EB4940D843C__INCLUDED_)
    ///////////////////////////////////////////////////////////////////////////
    // DSBuffer.cpp : Implementation of CDSBuffer class
    //
      

  9.   

    #include "stdafx.h"
    #include "DSBuffer.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif//设置如下两个全局变量控制音量:
    //用于控制背景音乐音量大小
    int   m_nBkGrdVolume = DSBVOLUME_MAX; 
    //用于控制音效音量大小
    int   m_nYinXiaoVolume= DSBVOLUME_MAX-DSBVOLUME_MIN ;  /////////////////////////////////////////////////////////////////////////////
    // CDSBufferCDSBuffer::CDSBuffer()
    {
    // 复位声音缓冲区
    m_lpDSBuffer = NULL;
    }CDSBuffer::CDSBuffer(const char *FileName,BOOL m_bBackGroundMusic,LPDIRECTSOUND lpDS, DWORD dwFlags)
    {
        //判断是否用于背景音乐
    //若m_bBackGroundMusic为TRUE,则该音乐用于背景音乐
    //若m_bBackGroundMusic为FALSE,则该音乐用于音效
    m_bBkGrdMusic=m_bBackGroundMusic; // 复位声音缓冲区
    m_lpDSBuffer = NULL;    // 打开wave文件       
    FILE* pFile = fopen(FileName, "rb");
    if(!pFile)
    return; // 把相关信息读入Wave header          
    WaveHeader wavHdr;
    if (fread(&wavHdr, sizeof(wavHdr), 1, pFile) != 1) 
    {
    fclose(pFile);
    return;
    } // 所需的数据区的大小
    DWORD dwSize = wavHdr.dwDSize; // 是否是一个立体声声音文件?
    BOOL bStereo = wavHdr.wChnls > 1 ? true : false; // 为这个wave文件创建声音缓冲区
    if(CreateSoundBuffer(lpDS, dwFlags, dwSize, wavHdr.dwSRate, wavHdr.BitsPerSample, wavHdr.wBlkAlign, bStereo))
    {
    // 从wave文件中读入声音数据
    if (!ReadData(pFile, dwSize, sizeof(wavHdr)))
    MessageBox(NULL,"读入声音数据出错",NULL,MB_OK);
    } fclose(pFile);
    }
    CDSBuffer::~CDSBuffer()
    {
    StopSound();
    if(m_lpDSBuffer)
    {       
    m_lpDSBuffer->Release();
    }
    }
    BOOL CDSBuffer::CreateSoundBuffer(LPDIRECTSOUND lpDS, DWORD dwFlags, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo)
    {
    PCMWAVEFORMAT pcmwf;
    DSBUFFERDESC dsbdesc; // 设置wave format结构.
    memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
    pcmwf.wf.wFormatTag         = WAVE_FORMAT_PCM;      
    pcmwf.wf.nChannels          = bStereo ? 2 : 1;
    pcmwf.wf.nSamplesPerSec     = dwFreq;
    pcmwf.wf.nBlockAlign        = (WORD)dwBlkAlign;
    pcmwf.wf.nAvgBytesPerSec    = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
    pcmwf.wBitsPerSample        = (WORD)dwBitsPerSample; // 设置DSBUFFERDESC结构
    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));  // Zero it out. 
    dsbdesc.dwSize              = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags             = dwFlags;
    dsbdesc.dwBufferBytes       = dwBufSize; 
    dsbdesc.lpwfxFormat         = (LPWAVEFORMATEX)&pcmwf; if (DS_OK != lpDS->CreateSoundBuffer(&dsbdesc, &m_lpDSBuffer, NULL))
    {
    MessageBox(NULL,"创建声音缓冲区失败",NULL,MB_OK);
    return FALSE;
    } return TRUE;
    }
    BOOL CDSBuffer::ReadData(FILE* pFile, DWORD dwSize, DWORD dwPos) 
    {
    // 定位到文件中的正确位置
    if (dwPos != 0xffffffff) 
    {
    if (fseek(pFile, dwPos, SEEK_SET) != 0) 
    {
    return FALSE;
    }
    } // 锁定缓冲区数据
    LPVOID pData1;
    DWORD  dwData1Size;
    LPVOID pData2;
    DWORD  dwData2Size;
    HRESULT rval; rval = m_lpDSBuffer->Lock(0, dwSize, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
    if (rval != DS_OK)
    {
    return FALSE;
    } // 读取数据
    if (dwData1Size > 0) 
    {
    if (fread(pData1, dwData1Size, 1, pFile) != 1) 
    {               
    return FALSE;
    }
    } if (dwData2Size > 0) 
    {
    if (fread(pData2, dwData2Size, 1, pFile) != 1) 
    {
    return FALSE;
    }
    } // 解除锁定
    rval = m_lpDSBuffer->Unlock(pData1, dwData1Size, pData2, dwData2Size);
    if (rval != DS_OK)
    {
    return FALSE;
    } return TRUE;
    }//入口参数:bContinue,控制调用StopSound后是否接着原来的播放点播放
    //                    bContinue为TRUE时接着原来点播放,为FALSE时从头播放
    //                    默认bContinue为FALSE
    BOOL CDSBuffer::PlaySound(BOOL bContinue)
    {
    if(m_lpDSBuffer) // 确认声音缓冲区有效
    {
    DWORD dwStatus;
    if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus))
    {
    MessageBox(NULL,"获取DirectSound缓冲区状态失败!",NULL,MB_OK);
    return FALSE;
    } if((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)
    {
    if (m_bBkGrdMusic)  //是背景音乐则循环播放
    {
    //设置播放位置
    if (!bContinue)
    m_lpDSBuffer->SetCurrentPosition(0); if (DS_OK != m_lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING)) // Play the sound
    {
    return FALSE;
    }
    }
    else    //是音效则播放一次停止
    {
    //设置播放位置
    if (!bContinue)
    m_lpDSBuffer->SetCurrentPosition(0); if (DS_OK != m_lpDSBuffer->Play(0, 0, 0)) // Play the sound
    {
    MessageBox(NULL,"不能播放声音缓冲区对象",NULL,MB_OK);
    return FALSE;
    }
    }
    }
    } return TRUE;
    }BOOL CDSBuffer::StopSound()
    {
    if(m_lpDSBuffer) // 确认声音缓冲区有效
    {
    DWORD dwStatus;
    if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus))
    {
    return FALSE;
    } if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
    {  
    if (DS_OK != m_lpDSBuffer->Stop()) // Stop the sound
    {
    return FALSE;
    } }
    }
    return TRUE;
    }
    BOOL CDSBuffer::IsValid()
    {
    if (m_lpDSBuffer)
    return TRUE;
    else
    return FALSE;
    }//------------音量控制部分---------------
    //SetVolume:设置音量
    //入口参数为百分数(0~100)
    void CDSBuffer::SetVolume(int percent)
    {
    int nVolume;
    if (percent<=0)
    nVolume=DSBVOLUME_MIN;
    else if (percent>=100)
    nVolume=DSBVOLUME_MAX;
    else
    nVolume=DSBVOLUME_MIN+(DSBVOLUME_MAX-DSBVOLUME_MIN)*percent/100;
        GetBuffer()->SetVolume(nVolume);
    }//以下两个函数用于控制音量大小
    //入口参数为百分数(0~100)
    void CDSBuffer::VolumeDown(int percent)
    {
    if (percent<=0 )
    percent=1;
    if (percent>=100)
    percent=100;
    if(m_bBkGrdMusic)    //如果是背景音乐,则设置背景音乐音量
    {
    if (m_nBkGrdVolume<=DSBVOLUME_MIN)
    {
    m_nBkGrdVolume=DSBVOLUME_MIN;
    GetBuffer()->SetVolume(m_nBkGrdVolume);
    return;
    }
    m_nBkGrdVolume-=(DSBVOLUME_MAX-DSBVOLUME_MIN)/percent;
    if (m_nBkGrdVolume<=DSBVOLUME_MIN)
    m_nBkGrdVolume=DSBVOLUME_MIN;
    GetBuffer()->SetVolume(m_nBkGrdVolume);
    }
    else                //是音效,则设置音效音量
    {
    if (m_nYinXiaoVolume<=DSBVOLUME_MIN)
    {
    m_nYinXiaoVolume=DSBVOLUME_MIN;
    GetBuffer()->SetVolume(m_nYinXiaoVolume);
    return;
    }
    m_nYinXiaoVolume-=(DSBVOLUME_MAX-DSBVOLUME_MIN)/percent;
    if (m_nYinXiaoVolume<=DSBVOLUME_MIN)
    m_nYinXiaoVolume=DSBVOLUME_MIN;
    GetBuffer()->SetVolume(m_nYinXiaoVolume);
    }}void CDSBuffer::VolumeUp(int percent)
    {
    if (percent<=0 )
    percent=1;
    if (percent>=100)
    percent=100;
        if (m_bBkGrdMusic)    //如果是背景音乐,则设置背景音乐音量
    {
    if (m_nBkGrdVolume>=DSBVOLUME_MAX)
    {
    m_nBkGrdVolume=DSBVOLUME_MAX;
    GetBuffer()->SetVolume(m_nBkGrdVolume);
    return;
    }
    m_nBkGrdVolume+=(DSBVOLUME_MAX-DSBVOLUME_MIN)/10;
    if (m_nBkGrdVolume>=DSBVOLUME_MAX)
    m_nBkGrdVolume=DSBVOLUME_MAX;
    GetBuffer()->SetVolume(m_nBkGrdVolume);
    }
    else                //是音效,则设置音效音量
    {
    if (m_nYinXiaoVolume>=DSBVOLUME_MAX)
    {
    m_nYinXiaoVolume=DSBVOLUME_MAX;
    GetBuffer()->SetVolume(m_nYinXiaoVolume);
    return;
    }
    m_nYinXiaoVolume+=(DSBVOLUME_MAX-DSBVOLUME_MIN)/10;
    if (m_nYinXiaoVolume>=DSBVOLUME_MAX)
    m_nYinXiaoVolume=DSBVOLUME_MAX;
    GetBuffer()->SetVolume(m_nYinXiaoVolume);
    }
    }
      

  10.   

    如何调用:
    // DSDemoDlg.cpp : implementation file
    //#include "stdafx.h"
    #include "DSDemo.h"
    #include "DSDemoDlg.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog
    {
    public:
    CAboutDlg();// Dialog Data
    //{{AFX_DATA(CAboutDlg)
    enum { IDD = IDD_ABOUTBOX };
    //}}AFX_DATA // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CAboutDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL// Implementation
    protected:
    //{{AFX_MSG(CAboutDlg)
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    };CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    //{{AFX_DATA_INIT(CAboutDlg)
    //}}AFX_DATA_INIT
    }void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CAboutDlg)
    //}}AFX_DATA_MAP
    }BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    //{{AFX_MSG_MAP(CAboutDlg)
    // No message handlers
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CDSDemoDlg dialogCDSDemoDlg::CDSDemoDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CDSDemoDlg::IDD, pParent)
    {
    //{{AFX_DATA_INIT(CDSDemoDlg)
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }void CDSDemoDlg::DoDataExchange(CDataExchange* pDX)
    {
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CDSDemoDlg)
    DDX_Control(pDX, ID_EFFECTVOLUME, m_SliderEffectVolume);
    DDX_Control(pDX, ID_BKVOLUME, m_SliderBKVolume);
    //}}AFX_DATA_MAP
    }BEGIN_MESSAGE_MAP(CDSDemoDlg, CDialog)
    //{{AFX_MSG_MAP(CDSDemoDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_NOTIFY(NM_RELEASEDCAPTURE, ID_BKVOLUME, OnReleasedcaptureBkvolume)
    ON_NOTIFY(NM_RELEASEDCAPTURE, ID_EFFECTVOLUME, OnReleasedcaptureEffectvolume)
    ON_BN_CLICKED(IDC_EFFECT, OnEffect)
    ON_BN_CLICKED(IDC_PLAYBKMUSIC, OnPlaybkmusic)
    ON_WM_CLOSE()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CDSDemoDlg message handlersBOOL CDSDemoDlg::OnInitDialog()
    {
    CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
    CString strAboutMenu;
    strAboutMenu.LoadString(IDS_ABOUTBOX);
    if (!strAboutMenu.IsEmpty())
    {
    pSysMenu->AppendMenu(MF_SEPARATOR);
    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    }
    } // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here
    //设置音量范围
    m_SliderBKVolume.SetRange(0,100);
    m_SliderEffectVolume.SetRange(0,100);
    //初始时的音量均设成最大值
    m_SliderBKVolume.SetPos(100);
    m_SliderEffectVolume.SetPos(100);
    //选中播放背景音乐复选框
    ((CButton*)GetDlgItem(IDC_PLAYBKMUSIC))->SetCheck(1);   //初始化DirectSound对象
    if(!InitializeDirectSound(*AfxGetMainWnd()))
    {
    AfxMessageBox("初始化DirectSound失败!",MB_OK);
    CDialog::OnOK();
    return TRUE  ;
    }
    //创建声音缓冲区
    m_lpBkGrdDSBuffer=new CDSBuffer("bk.wav",TRUE,m_lpDS);
        m_lpYinXiaoDSBuffer=new CDSBuffer("effect.wav",FALSE,m_lpDS);
    //播放背景音乐
    m_lpBkGrdDSBuffer->PlaySound(); return TRUE;  // return TRUE  unless you set the focus to a control
    }void CDSDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
    CAboutDlg dlgAbout;
    dlgAbout.DoModal();
    }
    else
    {
    CDialog::OnSysCommand(nID, lParam);
    }
    }// If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.void CDSDemoDlg::OnPaint() 
    {
    if (IsIconic())
    {
    CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
    int cxIcon = GetSystemMetrics(SM_CXICON);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    CRect rect;
    GetClientRect(&rect);
    int x = (rect.Width() - cxIcon + 1) / 2;
    int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
    dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
    CDialog::OnPaint();
    }
    }// The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CDSDemoDlg::OnQueryDragIcon()
    {
    return (HCURSOR) m_hIcon;
    }BOOL CDSDemoDlg::InitializeDirectSound(HWND hWnd)
    {
    // 创建背景音乐和音效DirectSound对象
    if (DS_OK != DirectSoundCreate(NULL, &m_lpDS, NULL))
    {
    ::MessageBox(NULL,"创建DirectSound对象失败\n找不到可利用的声音设备",NULL,MB_OK);
    return FALSE;
    } // 设置协作级别
    if (DS_OK != m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL))
    {
    ::MessageBox(NULL,"设置协作级别失败",NULL,MB_OK);
    return FALSE;
    } return TRUE;
    }void CDSDemoDlg::ClearDSBuffer()
    {
        m_lpBkGrdDSBuffer->StopSound();
    m_lpYinXiaoDSBuffer->StopSound();
    if (m_lpBkGrdDSBuffer)
    delete m_lpBkGrdDSBuffer;
    if (m_lpYinXiaoDSBuffer)
    delete m_lpYinXiaoDSBuffer;
    }void CDSDemoDlg::OnReleasedcaptureBkvolume(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    int nPos = m_SliderBKVolume.GetPos();
    m_lpBkGrdDSBuffer->SetVolume(nPos);

    *pResult = 0;
    }void CDSDemoDlg::OnReleasedcaptureEffectvolume(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    int nPos = m_SliderEffectVolume.GetPos();
    m_lpYinXiaoDSBuffer->SetVolume(nPos); *pResult = 0;
    }void CDSDemoDlg::OnEffect() 
    {
    m_lpYinXiaoDSBuffer->PlaySound();

    }void CDSDemoDlg::OnPlaybkmusic() 
    {
    CButton* pButton = (CButton*)GetDlgItem(IDC_PLAYBKMUSIC);
    BOOL bFlag = (pButton->GetCheck() == 1);
    if (bFlag) m_lpBkGrdDSBuffer->PlaySound();
    else m_lpBkGrdDSBuffer->StopSound();
    }
    void CDSDemoDlg::OnClose() 
    {
    // 删除声音缓冲区对象
    ClearDSBuffer();
    CDialog::OnClose();
    }
    //////////////////////////////////////////////////////////////我偷来的
      

  11.   

    To: WJZMLSH(美丽神话)
    不知道从Buffer中读取wave数据数据混音效果如何?