什么是音频均衡器?

通过均衡器 可以让声音达到不同的听觉效果:古典、爵士、流行、增强重低音、摇滚等等。如图是酷狗音乐播放器的均衡器界面:

在讨论均衡器的实现原理之前 先要介绍几个音频相关的名词:

频率
声音在一个周期的震动次数 单位是赫兹(hz)不同频率的声音 其音色是不一样的,频率越低声音就越低沉
人的耳朵能听到的频繁范围是20Hz~20000Hz
音色
不同频率的声音 听起来有不同的听觉感受
频段
以某个频率为中心、向两边延伸的频率范围 称之为频段
增益

标识衰减或增强声音的大小。单位是db,0代表不衰减也不增强,每6db为一个声压级,即6db标识声音增大一倍,-6db标识声音衰减到原来的一半

均衡器的实现原理  通过设置特定频段的增益,达到不同的播放效果。比如前面那张图片 是酷狗的古典效果设置图 从图中可以知道需要设置的各频段及增益值为:

60 hz为中心的频段:增益为 0db
170 hz为中心的频段:增益为 0db
370 hz为中心的频段:增益为 0db
600 hz为中心的频段:增益为 0db
1000 hz为中心的频段:增益为 0db
3000 hz为中心的频段:增益为 0db
6000 hz为中心的频段:增益为 -4db
12000 hz为中心的频段:增益为 -4db
14000 hz为中心的频段:增益为 -4db
1500 hz为中心的频段:增益为 -6db

如何通过DirectSound设置这些参数?使用DirectSound中的结构体:

typedef struct _DSFXParamEq
{FLOAT   fCenter;FLOAT   fBandwidth;FLOAT   fGain;
} DSFXParamEq, *LPDSFXParamEq;
FLOAT   fCenter;       中心频率,单位hz,取值范围是20Hz~20000Hz
FLOAT   fBandwidth;    频宽, 表示以fCenter为中心向两边延伸这么多的一个频段 取值范围是 1.0f~36.0f, 通常用12
FLOAT   fGain;         增益值 单位db,取值范围 -15.fdb~15.fdb, 0表示原音 建议不大于12db或小于-12db 否则会有杂音

DSound中有一个类 LPDIRECTSOUNDFXPARAMEQ8  可以用这个类 设置各频段的增益,以下是相关的代码

头文件中声明了如下数据成员:

IDirectSound8* m_pDS8;
IDirectSoundBuffer8* m_pDSBuffer8;
LPDIRECTSOUNDFXPARAMEQ8 m_pParamEQ8; // 用来设置频段的增益

注意:如果想使用均衡器功能 初始化DSound对象时 需要包含标识符DSBCAPS_CTRLFX,以下是初始化DSound的函数:

BOOL CDSoundPlayer::Init(HWND hWnd, int nSampleRate, int nChannel, int nBitsPerSample)
{assert(!m_bInited);IDirectSoundBuffer* pDSBuffer = NULL;IDirectSoundNotify8* pDSNotify = NULL;do {BREAK_IF_FAILED(DirectSoundCreate8(NULL, &m_pDS8, NULL));BREAK_IF_FAILED(m_pDS8->SetCooperativeLevel(hWnd, DSSCL_PRIORITY));DSBUFFERDESC desc = {};WAVEFORMATEX wf = {};desc.dwSize = sizeof(desc);desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFX | DSBCAPS_CTRLVOLUME;desc.dwBufferBytes = MAX_AUDIO_BUF * BUFFERNOTIFYSIZE;desc.lpwfxFormat = &wf;desc.lpwfxFormat->wFormatTag = WAVE_FORMAT_PCM;desc.lpwfxFormat->nChannels = nChannel;desc.lpwfxFormat->nSamplesPerSec = nSampleRate;desc.lpwfxFormat->nAvgBytesPerSec = nSampleRate * (nBitsPerSample / 8) * nChannel;desc.lpwfxFormat->nBlockAlign = (nBitsPerSample / 8) * nChannel;desc.lpwfxFormat->wBitsPerSample = nBitsPerSample;// 如果要使用DSound的某个功能 设置desc.dwFlags时 需要包含对应的标识符BREAK_IF_FAILED(m_pDS8->CreateSoundBuffer(&desc, &pDSBuffer, NULL));BREAK_IF_FAILED(pDSBuffer->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)&m_pDSBuffer8));// 设置事件通知ResetEvents();DSBPOSITIONNOTIFY aDSPosNotify[MAX_AUDIO_BUF] = {};for (int i = 0; i < MAX_AUDIO_BUF; i++){ aDSPosNotify[i].dwOffset = i * BUFFERNOTIFYSIZE;aDSPosNotify[i].hEventNotify = m_hEvents[i];}BREAK_IF_FAILED(m_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSNotify));BREAK_IF_FAILED(pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF, aDSPosNotify));// 获取均衡器对象DWORD dwResult;DSEFFECTDESC effectdesc = {};effectdesc.dwSize = sizeof(DSEFFECTDESC);effectdesc.dwFlags = 0;effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_PARAMEQ;BREAK_IF_FAILED(m_pDSBuffer8->SetFX(1, &effectdesc, &dwResult));BREAK_IF_FAILED(m_pDSBuffer8->GetObjectInPath(GUID_DSFX_STANDARD_PARAMEQ, 0, IID_IDirectSoundFXParamEq8, (LPVOID*)&m_pParamEQ8));m_bInited = TRUE;return TRUE;} while (0);SAFE_DELETE_COM(pDSBuffer);SAFE_DELETE_COM(pDSNotify);SAFE_DELETE_COM(m_pParamEQ8);SAFE_DELETE_COM(m_pDSBuffer8);SAFE_DELETE_COM(m_pDS8);return FALSE;
}

设置频段增益的函数:

BOOL CDSoundPlayer::SetEQ(float fFrequency, float fBandWidth, float fGain)
{assert(m_pParamEQ8);if (!m_pParamEQ8)return FALSE;DSFXParamEq paramsParamEq;paramsParamEq.fCenter = fFrequency;paramsParamEq.fBandwidth = fBandWidth;paramsParamEq.fGain = fGain;return SUCCEEDED(m_pParamEQ8->SetAllParameters(&paramsParamEq));
}

如果要设置前面酷狗的古典效果 函数调用如下:

 CDSoundPlayer player;player->Init(....); // 初始化DSoundplayer->SetEQ(60, 12, 0); player->SetEQ(170, 12, 0);player->SetEQ(370, 12, 0);player->SetEQ(600, 12, 0);player->SetEQ(1000, 12, 0);player->SetEQ(3000, 12, 0);player->SetEQ(6000, 12, -4);player->SetEQ(12000, 12, -4);player->SetEQ(14000, 12, -4);player->SetEQ(15000, 12, -6); player->Play();

是不是很简单?其他均衡器效果的各频段增益值 大家可参考酷狗或者qq音乐,也可以自行在网上搜索。

DSound还有其他很多稀奇古怪的特效 大家可参考这里自己尝试去实现这些功能。

[DirectSound] 基于DirectSound的音频均衡器实现相关推荐

  1. 基于MATLAB的高阶(两个二阶级联构成的四阶以及更高阶)数字图形音频均衡器系数计算(可直接用于DSP实现)

    引言 前不久,在数字信号处理中需要对音频信号进行滤波,涉及图形均衡器.参数均衡器的设计,下面这个链接给出了一个图形音频均衡器的例子: https://arm-software.github.io/CM ...

  2. 【信号处理】基于Matlab GUI数字均衡器设计,源码附上

    [信号处理]基于Matlab GUI数字均衡器设计,源码附上 数字均衡器是一种常用于音频信号处理的技术,可以有效地补偿声音中的频率失真,提高音质.在这篇文章中,我们将介绍如何使用Matlab GUI进 ...

  3. android8.1上musicfx,Android自带音频均衡器MusicFx分析

    Android自带音频均衡器MusicFx分析 种种原因,我要简单分析一个Android中built-in的音频均衡器MusicFx.重点是它的默认值的来历.网上很少有文章讲了这个的除了这篇<c ...

  4. 基于傅里叶变换的音频重采样算法 (附完整c代码)

    前面有提到音频采样算法: WebRTC 音频采样算法 附完整C++示例代码 简洁明了的插值音频重采样算法例子 (附完整C代码) 近段时间有不少朋友给我写过邮件,说了一些他们使用的情况和问题. 坦白讲, ...

  5. 基于 CoreAudio 的音频编解码(二):音频编码

    系列文章目录 基于 CoreAudio 的音频编解码(一):音频解码 基于 CoreAudio 的音频编解码(二):音频编码 前言 在 基于 CoreAudio 的音频编解码(一):音频解码 中,我们 ...

  6. 基于 CoreAudio 的音频编解码(一):音频解码

    系列文章目录 基于 CoreAudio 的音频编解码(一):音频解码 基于 CoreAudio 的音频编解码(二):音频编码 前言 Core Audio 是iOS和MAC系统中的关于数字音频处理的基础 ...

  7. 基于 FFMPEG 的音频编解码(三):音频编码

    音频编码 基于 FFMPEG 的音频编解码(一):Hello FFMPEG,安装与编译 基于 FFMPEG 的音频编解码(二):音频解码 基于 FFMPEG 的音频编解码(三):音频编码 在前面文章中 ...

  8. 基于 FFMPEG 的音频编解码(二):音频解码

    音频解码 基于 FFMPEG 的音频编解码(一):Hello FFMPEG,安装与编译 基于 FFMPEG 的音频编解码(二):音频解码 基于 FFMPEG 的音频编解码(三):音频编码 在 Hell ...

  9. 基于 FFMPEG 的音频编解码(一):Hello FFMPEG,安装与编译

    Hello FFMPEG 基于 FFMPEG 的音频编解码(一):Hello FFMPEG,安装与编译 基于 FFMPEG 的音频编解码(二):音频解码 基于 FFMPEG 的音频编解码(三):音频编 ...

最新文章

  1. 机器学习公开课~~~~mooc
  2. 解决onclick事件调用其它带参数的函数方法无效的问题
  3. KMP经典算法与变形的应用(字符串parttern匹配问题)
  4. 动态计算未知盒子的高度
  5. Asp.net主题(theme)和皮肤(skin)的使用
  6. 银行卡Bin查询接口
  7. Eclipse 官方简体中文语言包下载地址及安装方法
  8. 计算机密码怎么重置,电脑忘记密码了怎么重置密码
  9. vue3 + vite +ts 引入静态图片
  10. java 电子邮件客户端_java中的电子邮件客户端
  11. 手机版云盘怎么打开连接服务器,手把手教你简易NAS构建,手机/平板/智能电视随意调取,家庭存储云共享,有了自己的网络云盘后再也不用担心容量不够了!...
  12. 牛客网 2018年全国多校算法寒假训练营练习比赛(第二场) A.吐泡泡-STL(stack)
  13. MATLAB写UCB算法,科学网—【RL系列】Multi-Armed Bandit问题笔记——UCB策略实现 - 管金昱的博文...
  14. 【CSS】CSS选择器优先级及!important属性
  15. UEFI U盘安装Win10最简单的方法【转】
  16. 开发三年的Java程序员,如何摆脱日复一日的CRUD?
  17. 生产线标准工时怎么算?工厂管理者必须要知道的
  18. EasyPlayer-RTSP-Android安卓播放器播放RTSP延迟优化策略,极低延时!
  19. java 反射动态修改数据类型_[Java-基础]反射_Class对象_动态操作
  20. 线性规划问题及单纯形法-单纯形法计算步骤

热门文章

  1. python之pandas df.dropna()
  2. win7 scp命令的使用
  3. linux 用户和组之间的关系
  4. 【医学影像】MRI检查技术之:脊柱与脊髓
  5. Vuetify:从零开始安装Vuetify
  6. java学习笔记(一)int和Integer的区别
  7. JAVA 订阅推送快递100物流消息(一)
  8. 自然语言处理入门——白话机器翻译原理
  9. 神经网络入门最好的一篇文章
  10. 常用的简单校验算法:校验和,异或校验,crc校验,LRC校验,补码求和,checksum