啥叫混音呢,其实很简单,如果两个人同时说话 ,他们俩发出的声波在空气中进行了波的叠加,这其实就是个混音。计算机的混音,其实是一个虚拟的混音操作,因为计算机其实是只有一个声源(现在的计算机通常有两声道甚至5声道的立体声,先忽略这些,我们先抽象,把计算机看作一个声源),通过在计算机内部进行运算,把两个波形进行叠加运算,然后由计算机唯一的音箱输出,这就是计算机混音技术。微软的API PlaySound是不支持混音的,调用一个PlaySound的时候,会终止上一个PlaySound调用所播放的声音(异步调用),如果要用PlaySound来实现混音效果,就需要自己写一个混音算法。幸运的是,该叠加算法不需要我们去写,微软的DirectX早已提供给我们了现成的算法,而且非常强大,参与叠加的每个声音分量甚至都能够有自己独立的空间坐标,这也就是3D音效了。我们不需要3d音效,只要能够多路混音就可以了,晚上找到一个开源的对DirectSound的封装,非常好用,现把代码公开如下:

-------------------------------------------------------------------------------------------------

// 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>

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; // Sound buffer
LPDIRECTSOUND3DBUFFER m_lpDS3DBuffer; // 3D buffer

// Construction / Destruction
public:
CDSBuffer();
CDSBuffer(const char* FileName, LPDIRECTSOUND lpDS, DWORD dwFlags = DSBCAPS_CTRLDEFAULT);
~CDSBuffer();

// Methods
public:
BOOL PlaySound(DWORD dwFlags);
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;}
LPDIRECTSOUND3DBUFFER Get3DBuffer() { return m_lpDS3DBuffer;}
};

#endif // !defined(AFX_DSBUFFER_H__7517D749_96E3_11D2_BBF3_9EB4940D843C__INCLUDED_)

-------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------

///
// //
// DirectSound Mixer //
// //
// V1.0 by lob_b@hotmail.com 1999 //
// //
// with core inputs from //
// Stack-Up //
// V1.0 ?Tool@theWaterCooler.com 1998 //
// http://www.theWaterCooler.com/Tool //
// also Petr.Stejskal@vslib.cz //
// //
///

// DSBuffer.cpp : Implementation of CDSBuffer class
//

#include "stdafx.h"
#include "DSBuffer.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CDSBuffer

CDSBuffer::CDSBuffer()
{
// Reset the sound buffer
m_lpDSBuffer = NULL;

// Reset the 3D buffer
m_lpDS3DBuffer = NULL;
}

CDSBuffer::CDSBuffer(const char *FileName, LPDIRECTSOUND lpDS, DWORD dwFlags)
{
// Reset the sound buffer
m_lpDSBuffer = NULL;

// Reset the 3D buffer
m_lpDS3DBuffer = NULL;

// Open the wave file
FILE* pFile = fopen(FileName, "rb");
if(!pFile)
return;

// Read in the wave header
WaveHeader wavHdr;
if (fread(&wavHdr, sizeof(wavHdr), 1, pFile) != 1)
{
fclose(pFile);
return;
}

// Figure out the size of the data region
DWORD dwSize = wavHdr.dwDSize;

// Is this a stereo or mono file?
BOOL bStereo = wavHdr.wChnls > 1 ? true : false;

// Create the sound buffer for the wave file
if(CreateSoundBuffer(lpDS, dwFlags, dwSize, wavHdr.dwSRate, wavHdr.BitsPerSample, wavHdr.wBlkAlign, bStereo))
{
// Read the data for the wave file into the sound buffer
if (!ReadData(pFile, dwSize, sizeof(wavHdr)))
AfxMessageBox("Error - DS - Reading Data");
else if (dwFlags & DSBCAPS_CTRL3D)
{
// Get pointer to 3D buffer
if (S_OK != m_lpDSBuffer->QueryInterface(IID_IDirectSound3DBuffer, (void **)&m_lpDS3DBuffer))
AfxMessageBox("DirectSound3DBuffer not available");
}
}

fclose(pFile);
}

CDSBuffer::~CDSBuffer()
{
StopSound();
if(m_lpDSBuffer)
{
m_lpDSBuffer->Release();
}

if(m_lpDS3DBuffer)
{
m_lpDS3DBuffer->Release();
}
}

BOOL CDSBuffer::CreateSoundBuffer(LPDIRECTSOUND lpDS, DWORD dwFlags, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo)
{
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;

// Set up wave format structure.
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;

// Set up DSBUFFERDESC structure.
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))
{
AfxMessageBox("Error - DS - CreateSoundBuffer");
return FALSE;
}

return TRUE;
}

BOOL CDSBuffer::ReadData(FILE* pFile, DWORD dwSize, DWORD dwPos)
{
// Seek to correct position in file (if necessary)
if (dwPos != 0xffffffff)
{
if (fseek(pFile, dwPos, SEEK_SET) != 0)
{
return FALSE;
}
}

// Lock data in buffer for writing
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;
}

// Read in first chunk of data
if (dwData1Size > 0)
{
if (fread(pData1, dwData1Size, 1, pFile) != 1)
{
return FALSE;
}
}

// read in second chunk if necessary
if (dwData2Size > 0)
{
if (fread(pData2, dwData2Size, 1, pFile) != 1)
{
return FALSE;
}
}

// Unlock data in buffer
rval = m_lpDSBuffer->Unlock(pData1, dwData1Size, pData2, dwData2Size);
if (rval != DS_OK)
{
return FALSE;
}

return TRUE;
}

BOOL CDSBuffer::PlaySound(DWORD dwFlags)
{
if(m_lpDSBuffer) // Make sure we have a valid sound buffer
{
DWORD dwStatus;
if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus))
{
AfxMessageBox("Error - DS - GetStatus");
return FALSE;
}

if((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)
{
if (DS_OK != m_lpDSBuffer->Play(0, 0, dwFlags)) // Play the sound
{
AfxMessageBox("Error - DS - Play");
return FALSE;
}
}
}

return TRUE;
}

BOOL CDSBuffer::StopSound()
{
if(m_lpDSBuffer) // Make sure we have a valid sound buffer
{
DWORD dwStatus;
if (DS_OK != m_lpDSBuffer->GetStatus(&dwStatus))
{
AfxMessageBox("Error - DS - GetStatus");
return FALSE;
}

if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
{
if (DS_OK != m_lpDSBuffer->Stop()) // Stop the sound
{
AfxMessageBox("Error - DS - Stop");
return FALSE;
}

}
}
return TRUE;
}

BOOL CDSBuffer::IsValid()
{
if (m_lpDSBuffer)
return TRUE;
else
return FALSE;
}

-------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------

// DSList.h : Definition of CDSList class
//

#if !defined(AFX_DSLIST_H__7517D749_96E3_11D2_BBF3_9EB4940D843C__INCLUDED_)
#define AFX_DSLIST_H__7517D749_96E3_11D2_BBF3_9EB4940D843C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "DSBuffer.h"

class CDSList : virtual protected CObList
{
// Attribute
private:
LPDIRECTSOUND m_lpDS; // DirectSound Object

// Construction / Destruction
public:
CDSList();
~CDSList();

// Methods
public:
BOOL Init();
BOOL StopAllBuffers();
BOOL AddNewBuffer(const char* FileName);
BOOL RemoveBuffer(int nBuffer);
BOOL PlayBuffer(int nBuffer, DWORD dwFlags);
BOOL StopBuffer(int nBuffer);
LPDIRECTSOUND GetDSObject() {return m_lpDS;}
};

#endif // !defined(AFX_DSLIST_H__7517D749_96E3_11D2_BBF3_9EB4940D843C__INCLUDED_)

-------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------

///
// //
// DirectSound Mixer //
// //
// V1.0 by lob_b@hotmail.com 1999 //
// //
// with core inputs from //
// Stack-Up //
// V1.0 ?Tool@theWaterCooler.com 1998 //
// http://www.theWaterCooler.com/Tool //
// also Petr.Stejskal@vslib.cz //
// //
///

// DSList.cpp : Implementation of CDSList class
//

#include "stdafx.h"
#include "DSList.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CDSList

CDSList::CDSList()
{
// Reset the DirectSound pointer
m_lpDS = NULL;
}

CDSList::~CDSList()
{
// Stop all playing buffers
StopAllBuffers();

if(m_lpDS)
{
m_lpDS->Release();
}
}

BOOL CDSList::Init()
{
// Create DirectSound Object
if (DS_OK != DirectSoundCreate(NULL, &m_lpDS, NULL))
{
AfxMessageBox("Error - DS - Create/nAudio cannot be used");
return FALSE;
}

// Set Cooperative Level
if (DS_OK != m_lpDS->SetCooperativeLevel(*AfxGetMainWnd(), DSSCL_NORMAL))
{
AfxMessageBox("Error - DS - SetCooperativeLevel");
return FALSE;
}

return TRUE;
}

BOOL CDSList::AddNewBuffer(const char* FileName)
{
// Make sure that audio is initialized
if (!m_lpDS)
{
AfxMessageBox("Error - DS - Audio not initialized");
return FALSE;
}

// Try creating the new buffer
CDSBuffer* pNewBuffer = new CDSBuffer(FileName, m_lpDS);

// If succesfull add to playlist
if (pNewBuffer->IsValid())
{
AddTail(pNewBuffer);
return TRUE;
}

// Else forget it
else
{
delete(pNewBuffer);
return FALSE;
}
}

BOOL CDSList::RemoveBuffer(int nBuffer)
{
// Make sure that the buffer index is valid
if ((nBuffer < 0) || (nBuffer >= GetCount()))
{
AfxMessageBox("Error - DS - Invalid buffer selection index");
return FALSE;
}

// First stop the buffer
if (StopBuffer(nBuffer))
{
// Find the buffer
POSITION Pos = FindIndex(nBuffer);

// Remove it
RemoveAt(Pos);
return TRUE;
}
return FALSE;
}

BOOL CDSList::PlayBuffer(int nBuffer, DWORD dwFlags)
{
// Make sure that the buffer index is valid
if ((nBuffer < 0) || (nBuffer >= GetCount()))
{
AfxMessageBox("Error - DS - Invalid buffer selection index");
return FALSE;
}

// Find the buffer
POSITION Pos = FindIndex(nBuffer);

// Retrieve a pointer
CDSBuffer* DSBuffer = (CDSBuffer *)GetAt(Pos);

// Try playing it
return DSBuffer->PlaySound(dwFlags);
}

BOOL CDSList::StopBuffer(int nBuffer)
{
// Make sure that the buffer index is valid
if ((nBuffer < 0) || (nBuffer >= GetCount()))
{
AfxMessageBox("Error - DS - Invalid buffer selection index");
return FALSE;
}

// Find the buffer
POSITION Pos = FindIndex(nBuffer);

// Retrieve a pointer
CDSBuffer* DSBuffer = (CDSBuffer *)GetAt(Pos);

// Try stopping it
return DSBuffer->StopSound();
}

BOOL CDSList::StopAllBuffers()
{
for (POSITION Pos = GetHeadPosition(); Pos != NULL; )
{
CDSBuffer* DSBuffer = (CDSBuffer *)GetNext(Pos);
DSBuffer->StopSound();
}
return TRUE;
}

-------------------------------------------------------------------------------------------------

代码使用方法:

1、首先把四个文件添加到工程中。

2、包含相应的头文件,在自己的代码中添加如下代码:

#include "DSList.h"

3、链接DirectSound的相关静态链接库

在自己的代码中加入如下静态链接代码:
//连接LIB库
#pragma comment (lib,"winmm.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"dsound.lib")

4、在初始化代码中载入波形文件到缓冲区:

代码示例:

//初始化DirectSound混音器;
m_dslist.Init ();
m_dslist.AddNewBuffer(GetAppPath()+"//sound//one.wav");
m_dslist.AddNewBuffer(GetAppPath()+"//sound//two.wav");
m_dslist.AddNewBuffer(GetAppPath()+"//sound//three.wav");

5、在需要播放声音的时候调用:m_dslist.PlayBuffer(index,0);

index参数指的是添加缓冲区索引,最先添加的缓冲区索引为0,依此类推。

该函数是异步执行,自动与以前调用该函数所产生的尚未结束的声音混音输出。

转载于:https://www.cnblogs.com/lzhitian/archive/2012/02/13/2348601.html

DirectSound 混音的实现相关推荐

  1. 利用Directsound编程实现实时混音

    在游戏开发中比较常用的音效素材都是比较短的,所以一般常用的API是playsound()函数,比如我们要在游戏背景中播放一个test.wav音效素材,只要简单的调用下面的函数即可 PlaySound( ...

  2. android html5播放器,android Html5播放器混音解决方案

    背景 当一个用户正在听音乐而另一个应用需要通知用户一些重要的事情时,用户可能由于音乐声音大而不能听的通知.从Android2.2开始,平台为应用提供了一个协商它们如何使用设备音频输出的途径,这个机制叫 ...

  3. 【Android FFMPEG 开发】Android 中使用 FFMPEG 对 MP3 文件进行混音操作

    文章目录 一.前置操作 ( 移植 FFMPEG ) 二.FFMPEG 混音命令 三.Android FFMPEG 混音源代码完整示例 四.博客源码 一.前置操作 ( 移植 FFMPEG ) 参考 [A ...

  4. 输入监听_更适合混音师的声卡 精准控制 多设备监听真的方便

    随着声音越来越被大家重视,想要提升音质,同时又不想太累赘,便携式声卡的春天再一次到来,Audient 也借此势头,升级了ID14 MK2,对比上一代,ID14 MK2没有很大的变化,体积大小都保持一致 ...

  5. 无失真压缩法可以减少冗余_混音笔记(七)——压缩器(2)压缩器参数调节方法...

    上一篇总结了压缩器的基本参数概念,这篇总结压缩器的参数调节思路与使用方法. 一.门限如何设置 设置门限的一个关键思路就是你的压缩目的是什么,比如我只想把峰值压一压,或者我想让细节更突出一点,亦或者我是 ...

  6. win7录制系统声音 加入立体声混音 camtasia recorder录屏

    很多时候,我们录屏的时候都并不是非得通过麦克风来说话,比如,你想跟好友分享一首歌曲的时候,那么你总不能把麦拿到喇叭那儿录制噻,那样录出来的不仅很麻烦,而且歌曲质量很差!那么怎么录制系统正在播放的声音 ...

  7. ffmpeg进行混音,将两路音频pcm数据合成一路输出

    ffmpeg进行混音,将两路音频pcm数据合成一路输出 audiomixer.h #ifndef AUDIOMIXER_H #define AUDIOMIXER_H#include <map&g ...

  8. android 混音 源码,FFmpegAndroid android 端基于 FFmpeg 实现音频剪切、拼接、转码、混音、编解码;视频剪切、水印、截图、转码、编 @codeKK c开源站...

    android 端基于 FFmpeg 库的使用 添加编译 ffmpeg.shine.mp3lame.x264 源码的参考脚本 目前音视频相关处理: 音频剪切.拼接 音频混音 音频转码 音视频合成 音频 ...

  9. 实时音频混音技术在视频直播中的实践应用

    作者:冼牛 转自:前端之巅 最近半年,视频直播领域中产生不少创新玩法,其中包括 K 歌直播和合唱直播.这些创新玩法都用到实时音频混音技术.今天我们来聊一下混音技术的实现,及其在创新玩法中的应用. 混音 ...

最新文章

  1. 阿里2018营收2502亿元,云计算业务增幅超100%
  2. 字符串 拼接方法,公司内部的方法,用集合转换成拼接的字符串
  3. 历史性难题——如何为Kafka挑选合适的分区数?
  4. 【转】Spring 的下载、安装和使用
  5. 嵌入式android pdf,Embedded Android 英文原版PDF
  6. iOS逆向工程——非越狱调试
  7. nssl1258-naive的瓶子【贪心】
  8. 2018年计算机二级MySQL真题_2018年3月计算机二级考试MySQL真题及答案2
  9. servlet容器开发要点
  10. 深度学习知识点全面总结
  11. ×××全功能邮件系统(6)
  12. window.print设置目标打印机_愿得一人心,白首不相离, 极印手机照片打印机入手体验...
  13. 微信小程序图片转换成文字_涨知识!这个微信小程序,能将纸上文字转换成电子版...
  14. 未来教育计算机书,未来教育计算机二级
  15. html怎么插入word文档,word中怎样插入html代码?
  16. 没完全读懂的《人间失格》
  17. 解决破解版matlab2018a打开示例或者帮助需要登录账号或者需要输入激活码问题
  18. pyside2安装后打开designer.exe文件提示丢失 MSVCP140.dll的处理方法
  19. 【PTA】读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。c。
  20. google新搜索网站

热门文章

  1. ADC实验(读取引脚电压值)
  2. mysql open-files-limit_在mysql 5.5中更改open-files-limit
  3. 计算机系统基础:文件的存取和存储空间管理知识笔记
  4. Java 13,最新最全新特性解读
  5. 这10个好习惯助你成为优秀的程序员
  6. python fsolve说明_Python fsolve()抱怨形状.为什么?
  7. apollo java客户端_携程配置中心Apollo的Java客户端API的使用
  8. 变频器按启动没反应_起重机软启动柜晶闸管损坏维修几大故障
  9. 关于python3中的包operator(支持函数式编程的包)
  10. python爬虫框架--scrapy 基本使用