啥叫混音呢,其实很简单,如果两个人同时说话 ,他们俩发出的声波在空气中进行了波的叠加,这其实就是个混音。计算机的混音,其实是一个虚拟的混音操作,因为计算机其实是只有一个声源(现在的计算机通常有两声道甚至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. 漫话:如何给女朋友解释什么是系统可用性?
  2. android ios 上传图片到服务器,.net 接收ios, android的上传图片
  3. 12.PHP_PDO数据库抽象层
  4. 使用SAP Spartacus快速创建一个电商店铺网站
  5. C++实现dijkstra单源最短路径算法-邻接表+优先队列
  6. linux的mysql小记
  7. babyion 加载obj模型_在vue中使用babylonjs引入3d模型,打印mesh数据正常且无报错,但未在场景中显示,请问是什么环节出现了问题?...
  8. 恕我直言,你可能误解了微服务
  9. myeclipse中加入jad查看jar源代码
  10. [Python] 对 Python 装饰器的理解心得
  11. 怎么提高计算机的桌面性能,电脑卡顿怎么办?4个小技巧帮你解决问题
  12. 电子游戏数据分析报告
  13. windows cmd批处理终端 快速编辑模式
  14. 今天Delphi盒子打不开了
  15. linux文件压缩和打包
  16. javaWeb项目加入IP黑白名单
  17. 【程序人生】《你相信上帝的存在吗?》
  18. 高性能网络编程之 Reactor 网络模型(彻底搞懂)
  19. 无法通过终端(远程桌面)服务启动MATLAB的解决办法
  20. 这些有趣的AI人脸特效背后,腾讯云都做了什么?

热门文章

  1. .NET基础 (03)生成、部署和管理
  2. 自定义快捷命令程序(VC++加批处理)
  3. 让Spring架构减化事务配置(转)
  4. Indy中判断邮件来源
  5. TwinSocketStream
  6. 计算机结构原理初步教案板书设计,(计算机工作原理)教学设计(教案)
  7. java 内存和实际内存_请问更改eclipse内存和更改jvm内存是一会事儿吗?
  8. linux进程互斥要点,linux进程之间互斥
  9. 在linux中500g怎么分区,500G的硬盘,怎么分区比较合理?
  10. cmos存储器中存放了_CMOS存储器中存放了计算机的一些参数和信息,其中不包含在内的是( )。_学小易找答案...