博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
音频增益响度分析 ReplayGain 附完整C代码示例
阅读量:6961 次
发布时间:2019-06-27

本文共 4116 字,大约阅读时间需要 13 分钟。

人们所熟知的图像方面的3A算法有:

AF自动对焦(Automatic Focus)

自动对焦即调节摄像头焦距自动得到清晰的图像的过程

AE自动曝光(Automatic Exposure)

自动曝光的是为了使感光器件获得合适的曝光量

AW自动白平衡(Automatic White Balance)

白平衡的本质是使白色物体在任何光源下都显示白色

 

与之相对应的音频方面的3A算法是:

AGC自动增益补偿(Automatic Gain Control)

自动调麦克风的收音量,使与会者收到一定的音量水平,不会因发言者与麦克风的距离改变时,声音有忽大忽小声的缺点。

ANS背景噪音抑制(Automatic Noise Suppression)

探测出背景固定频率的杂音并消除背景噪音。

AEC是回声消除器(Acoustic Echo Canceller)

对扬声器信号与由它产生的多路径回声的相关性为基础,建立远端信号的语音模型,利用它对回声进行估计,并不断地修改滤波器的系数,使得估计值更加逼近真实的回声。然后,将回声估计值从话筒的输入信号中减去,从而达到消除回声的目的,AEC还将话筒的输入与扬声器过去的值相比较,从而消除延长延迟的多次反射的声学回声。根椐存储器存放的过去的扬声器的输出值的多少,AEC可以消除各种延迟的回声。

 

 图像方面的算法就不多说了,图像方面的3a算法,本人都实现了。

自动白平衡的主要思路,就是如何判断图像是否偏色,偏色后如何修复的问题。

常见的有直方图均衡,自动对比度,自动色阶等等。

自动曝光也是要做曝光评估,常见的有gama调节等等。

后续有时间,再陆续贴出相应的代码。

在这里,先卖个关子,占个坑。

 

而在音频算法方面,自动增益补偿的算法有点类似图像的自动曝光算法。

主要要考虑的是多长的音频,怎么分析当前音频的音量或者强度。

根据这个强度对整个音频做一个归一化拉伸,诸如此类。

图像与音频殊途同归。

而历史悠久的算法,莫过于,ReplayGain

ReplayGain是David Robinson在2001年发布的一项建议标准,用于衡量计算机 中音频的。

相关的维基资料:

现在大多数的音频播放器都支持这个特性。

根据维基上的说明,现在大多数使用的开源实现是 

资料见:

开源项目地址:

项目是C代码,非常干净。

主要的算法实现文件见:gain_analysis.h 与 gain_analysis.c

算法是根据传入的音频数据,分析需要进行增益的分贝值。

不需要增益则为0,需要增益则为对应的浮点正数或负数。

当然,不能传入太少的音频样本,否则无法客观分析。

算法只需要传入音频的数据和指定需要分析的样本长度即可。

最终输出一个 推荐增益的分贝值。

根据这个分贝值进行换算,即可以对目标音频做一些特定的音频处理。

 

贴上完整的C代码:

#ifdef __cplusplusextern "C" {#endif#include 
#include
#include
//采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码#define DR_WAV_IMPLEMENTATION#include "dr_wav.h"#include "gain_analysis.h"#ifndef min#define min(a, b) (((a) < (b)) ? (a) : (b))#endif//读取wav文件int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint64_t *totalSampleCount) { unsigned int channels; int16_t *buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount); if (buffer == NULL) { printf("读取wav文件失败."); } //仅仅处理单通道音频 if (channels != 1) { drwav_free(buffer); buffer = NULL; *sampleRate = 0; *totalSampleCount = 0; } return buffer;}float getGaindB(int16_t *buffer, size_t totalSampleCount, int sampleRate, size_t analyzeSamples) { float ret = -0.00000000001f; if (totalSampleCount == 0) return ret; if (analyzeSamples == 0) return ret; const int maxSamples = 2400; analyzeSamples = min(maxSamples, analyzeSamples); ret = 1.0f; int num_channels = 1; Float_t inf_buffer[maxSamples]; size_t totalCount = totalSampleCount / analyzeSamples; if (InitGainAnalysis(sampleRate) == INIT_GAIN_ANALYSIS_OK) { int16_t *input = buffer; for (int i = 0; i < totalCount; i++) { for (int n = 0; n < analyzeSamples; n++) { inf_buffer[n] = input[n]; } if (AnalyzeSamples(inf_buffer, NULL, analyzeSamples, num_channels) != GAIN_ANALYSIS_OK) break; GetTitleGain(); // printf("Recommended dB change for analyzeSamples %d: %+6.2f dB\n", i, titleGain); input += analyzeSamples; } ret = GetAlbumGain(); } if ((int) ret == GAIN_NOT_ENOUGH_SAMPLES) { ret = -0.00000000001f; } return ret;}void analyze(char *in_file, int ref_ms) { uint32_t sampleRate = 0; uint64_t totalSampleCount = 0; int16_t *wavBuffer = wavRead_int16(in_file, &sampleRate, &totalSampleCount); if (wavBuffer != NULL) { size_t analyzeSamples = ref_ms * (sampleRate / 1000); float gain = getGaindB(wavBuffer, totalSampleCount, sampleRate, analyzeSamples); printf("recommended dB change: %f \n", gain); free(wavBuffer); }}int main(int argc, char *argv[]) { printf("Replay Gain Analysis\n"); printf("blog:http://cpuimage.cnblogs.com/\n"); printf("e-mail:gaozhihan@vip.qq.com\n"); if (argc < 2) return -1; char *in_file = argv[1]; //指定分析长度1秒 int ref_ms = 1000; analyze(in_file, ref_ms); getchar(); printf("press any key to exit. \n"); return 0;}#ifdef __cplusplus}#endif

我的习惯,尽量少些注释,代码尽量干净整洁。

所以大家直接看代码吧。

项目地址:

 

示例具体流程为:

加载wav(拖放wav文件到可执行文件上)->输出结果->保存wav

 

得到对应的评估结果之后,接下来作何处理,就看各位看官的具体需求了。

 

若有其他相关问题或者需求也可以邮件联系俺探讨。

邮箱地址是:

gaozhihan@vip.qq.com

 

转载于:https://www.cnblogs.com/cpuimage/p/8846951.html

你可能感兴趣的文章
MySQL索引背后的数据结构及算法原理
查看>>
全面剖析 Knative Eventing 0.6 版本新特性
查看>>
流,用声明性的方式处理数据集 - 读《Java 8实战》
查看>>
【翻译】How To Become A Blockchain Developer: Crash Course! 区块链开发指南!
查看>>
linux修改或者配置IP地址、网络YUM源(针对Centos)
查看>>
MVC Cookie的使用
查看>>
mysql主从配置
查看>>
Linux 消耗CPU和内存的代码段----测试用的
查看>>
VMware与Hyper-V不兼容
查看>>
OSX加载驱动提示invalid signature
查看>>
第0篇.C++开发环境介绍
查看>>
Ubuntu 源代码阅读和函数、变量的定位--之一
查看>>
Java - Keywords 基本数据类型 Identifier
查看>>
我的友情链接
查看>>
Core Linux 操作文档(一)
查看>>
hadoop安装过程中ubuntu系统ssh免密码登陆设置 
查看>>
input按钮的background-image属性兼容性问题
查看>>
java.lang.*不用我们导入,编译器会自动给我们导入的,,,这个包是默认导入的。...
查看>>
shell 小脚本
查看>>
IE8、IE9下访问博客报不安全『博客帮助』文档
查看>>