分享用于学习C++音频处理的代码示例
与《分享用于学习C++图像处理的代码示例》为姊妹篇。
为了便于学习C++音频处理并研究音频算法,
俺写了一个适合初学者学习的小小框架。
麻雀虽小五脏俱全,仅仅考虑单通道处理。
采用Decoder:dr_wav
https://github.com/mackron/dr_libs/blob/master/dr_wav.h
采用Encoder:原本计划采用dr_wav的Encode,但是dr_wav保存的文件头忘记修正音频数据的大小,
采用博主自己实现的代码,仅供学习之用。
dr_wav用于解析wav文件格式.
关于wav格式的解析移步至:
http://soundfile.sapp.org/doc/WaveFormat/
个人习惯,采用int16的处理方式,也可以通过简单的修改,改为float类型。
wav音频样本可以从维基百科上(https://en.wikipedia.org/wiki/WAV)下载。
注:少数wav格式不支持
Format | Bitrate (kbit/s) | 1 minute (KiB) | Sample |
---|---|---|---|
11,025 Hz 16 bit PCM | 176.4 | 1292 | 11k16bitpcm.wav |
8,000 Hz 16 bit PCM | 128 | 938 | 8k16bitpcm.wav |
11,025 Hz 8 bit PCM | 88.2 | 646 | 11k8bitpcm.wav |
11,025 Hz µ-Law | 88.2 | 646 | 11kulaw.wav |
8,000 Hz 8 bit PCM | 64 | 469 | 8k8bitpcm.wav |
8,000 Hz µ-Law | 64 | 469 | 8kulaw.wav |
11,025 Hz 4 bit ADPCM | 44.1 | 323 | 11kadpcm.wav |
8,000 Hz 4 bit ADPCM | 32 | 234 | 8kadpcm.wav |
11,025 Hz GSM 06.10 | 18 | 132 | 11kgsm.wav |
8,000 Hz MP3 16 kbit/s | 16 | 117 | 8kmp316.wav |
8,000 Hz GSM 06.10 | 13 | 103 | 8kgsm.wav |
8,000 Hz Lernout & Hauspie SBC 12 kbit/s | 12 | 88 | 8ksbc12.wav |
8,000 Hz DSP Group Truespeech | 9 | 66 | 8ktruespeech.wav |
8,000 Hz MP3 8 kbit/s | 8 | 60 | 8kmp38.wav |
8,000 Hz Lernout & Hauspie CELP | 4.8 | 35 | 8kcelp.wav |
附带处理耗时计算,示例演示了一个简单的将音频前面一半静音处理,并简单注释了一下部分逻辑。
完整代码:
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <time.h> #include <iostream> //采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码 #define DR_WAV_IMPLEMENTATION #include "dr_wav.h" auto const epoch = clock(); static double now() { return (clock() - epoch); }; template <typename FN> static double bench(const FN &fn) { auto took = -now(); ; } //写wav文件 void wavWrite_int16(char* filename, int16_t* buffer, int sampleRate, uint32_t totalSampleCount) { FILE* fp = fopen(filename, "wb"); if (fp == NULL) { printf("文件打开失败.\n"); return; } //修正写入的buffer长度 totalSampleCount *= sizeof(int16_t); ; ; ; ] = { 'R', 'I', 'F', 'F' }; uint32_t long_number = + totalSampleCount; fwrite(text, , , fp); fwrite(&long_number, , , fp); text[] = 'W'; text[] = 'A'; text[] = 'V'; text[] = 'E'; fwrite(text, , , fp); text[] = 'f'; text[] = 'm'; text[] = 't'; text[] = ' '; fwrite(text, , , fp); long_number = ; fwrite(&long_number, , , fp); int16_t short_number = FORMAT_PCM;//默认音频格式 fwrite(&short_number, , , fp); short_number = ; // 音频通道数 fwrite(&short_number, , , fp); long_number = sampleRate; // 采样率 fwrite(&long_number, , , fp); long_number = sampleRate * nbyte; // 比特率 fwrite(&long_number, , , fp); short_number = nbyte; // 块对齐 fwrite(&short_number, , , fp); short_number = nbit; // 采样精度 fwrite(&short_number, , , fp); ] = { 'd', 'a', 't', 'a' }; fwrite(data, , , fp); long_number = totalSampleCount; fwrite(&long_number, , , fp); fwrite(buffer, totalSampleCount, , fp); fclose(fp); } //读取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文件失败."); } //仅仅处理单通道音频 ) { drwav_free(buffer); buffer = NULL; *sampleRate = ; *totalSampleCount = ; } return buffer; } //分割路径函数 void splitpath(const char* path, char* drv, char* dir, char* name, char* ext) { const char* end; const char* p; const char* s; ] && path[] == ':') { if (drv) { *drv++ = *path++; *drv++ = *path++; *drv = '\0'; } } else if (drv) *drv = '\0'; for (end = path; *end && *end != ':';) end++; for (p = end; p > path && *--p != '\\' && *p != '/';) if (*p == '.') { end = p; break; } if (ext) for (s = end; (*ext = *s++);) ext++; for (p = end; p > path;) if (*--p == '\\' || *p == '/') { p++; break; } if (name) { for (s = p; s < end;) *name++ = *s++; *name = '\0'; } if (dir) { for (s = path; s < p;) *dir++ = *s++; *dir = '\0'; } } int main(int argc, char* argv[]) { std::cout << "Audio Processing " << std::endl; std::cout << "博客:http://tntmonks.cnblogs.com/" << std::endl; std::cout << "支持解析单通道wav格式." << std::endl; ) ; ]; //音频采样率 uint32_t sampleRate = ; //总音频采样数 uint64_t totalSampleCount = ; int16_t* wavBuffer = NULL; double nLoadTime = bench([&] { wavBuffer = wavRead_int16(in_file, &sampleRate, &totalSampleCount); }); std::cout << ) << " 毫秒" << std::endl; //如果加载成功 if (wavBuffer != NULL) { //将前面一般进行静音处理,直接置零即可 ; i < totalSampleCount / ; i++) { wavBuffer[i] = ; } } //保存结果 double nSaveTime = bench([&] { ]; ]; ]; ]; ]; splitpath(in_file, drive, dir, fname, ext); sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext); wavWrite_int16(out_file, wavBuffer, sampleRate, totalSampleCount); }); std::cout << ) << " 毫秒" << std::endl; getchar(); std::cout << "按任意键退出程序 \n" << std::endl; ; }
示例具体流程为:
加载wav(拖放wav文件到可执行文件上)->简单静音处理->保存wav
并对 加载,保存 这2个环节都进行了耗时计算并输出。
若有其他相关问题或者需求也可以邮件联系俺探讨。
邮箱地址是:
gaozhihan@vip.qq.com
若此博文能帮到您,欢迎扫码小额赞助。
微信:
支付宝:
分享用于学习C++音频处理的代码示例的更多相关文章
- 分享用于学习C++图像处理的代码示例
为了便于学习图像处理并研究图像算法, 俺写了一个适合初学者学习的小小框架. 麻雀虽小五脏俱全. 采用的加解码库:stb_image 官方:http://nothings.org/ stb_image. ...
- 分享一些学习资料-大量PDF电子书
分享一些学习用的电子书籍,给那些喜欢看书而不一定有机会买书的童鞋. 反对积分下载,提倡自由分享. 分享地址: http://pan.baidu.com/s/1qWK5V0g 提取密码: np33 ...
- 嵌入式 十个最值得阅读学习的C开源项目代码
开源世界有许多优秀的开源项目,我选取其中十个最优秀的.最轻量级的C语言的项目,希望可以为C语言开发人员提供参考. 十个最值得阅读学习的C开源项目代码 1. Webbench 2. Tinyhttpd ...
- Delphi之通过代码示例学习XML解析、StringReplace的用法(异常控制 good)
*Delphi之通过代码示例学习XML解析.StringReplace的用法 这个程序可以用于解析任何合法的XML字符串. 首先是看一下程序的运行效果: 以解析这样一个XML的字符串为例: <? ...
- 分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要)
原文:分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要) Java InputStream读取数据问题 ======== ...
- ffmpeg音频播放代码示例-avcodec_decode_audio4
一.概述 最近在学习ffmpeg解码的内容,参考了官方的教程http://dranger.com/ffmpeg/tutorial03.html,结果发现这个音频解码的教程有点问题.参考了各种博客,并同 ...
- 音频增益响度分析 ReplayGain 附完整C代码示例
人们所熟知的图像方面的3A算法有: AF自动对焦(Automatic Focus)自动对焦即调节摄像头焦距自动得到清晰的图像的过程 AE自动曝光(Automatic Exposure)自动曝光的是为了 ...
- 音频增益响度分析 ReplayGain 附完整C代码示例【转】
转自:http://www.cnblogs.com/cpuimage/p/8846951.html 人们所熟知的图像方面的3A算法有: AF自动对焦(Automatic Focus)自动对焦即调节摄像 ...
- .net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能
原文:.net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能 接上篇,上篇已经学习了界面的各种功能以及各种配置,这篇准备学习下代码控制许可证. ...
随机推荐
- 谈谈单元測试之(二):測试工具 JUnit 3
前言 上一篇文章<为什么要进行烦人的单元測试?>讨论了一下现阶段软件开发中,程序猿们測试情况的现状.这篇文章中,我打算介绍一下单元測试的工具(插件).而且推荐大家以后在开发中,真正的用上单 ...
- [UWP]了解模板化控件(7):支持Command
以我的经验来说,要让TemplatedControl支持Command的需求不会很多,大部分情况用附加属性解决这个需求会更便利些,譬如UWPCommunityToolkit的HyperlinkExte ...
- 《分布式系统原理介绍》【PDF】下载
内容简介 分布式系统理论体系非常庞大,涉及知识面也非常广博,本文精心选择了部分在工程实践中应用广泛.简单有效的分布式理论.算法.协议加以介绍.全文分为两大部分,第一部分介绍了分布式系统的一些基本概念并 ...
- 实现我博客旁边的线条效果 html canvas-nest.js 源码
canvas-nest.js 这个js文件可以用来实现炫酷的线条与鼠标进行交互的功能,具体效果如图所示 js具体源码如下: /** * Copyright (c) 2016 hustcc * Lice ...
- 学习Lua setmetatable Lua 元表
Lua 元表(Metatable) 在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作. 个人理解,这个相当于其他语言的继承,是把这个类的方法 ...
- 理解cocoa和cocoa touch的响应者链
该文章翻译自:Understanding cocoa and cocoa touch responder chain. 转载注明出处:http://www.cnblogs.com/zhanggui/p ...
- javaweb添加拦截器
js请求后台代码添加拦截器: package com.ctzj.biz.isale.deploy.controller; import java.io.IOException; import java ...
- 利用jquery实现电商网站常用特效之:五星评分
这篇文章主要为大家详细介绍了基于jquery实现五星好评,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 在电商网站,我们经常会用到五星评分的功能,现在用jQuery实现一个简单的demo: 1.引 ...
- grep 与 find 简单命令
在使用linux的时候,经常会用到查找文件或者查找文本,下面介绍两个命令. grep 使用方法: // 在当前目录下递归查找class字符串 grep "string" -r . ...
- DCL的失效:现实与初衷的背离
最近看了Brian Goetz写的一篇有关DCL的文章:Double-checked locking: Clever, but broken.( 2001年发表于JavaWorld上) 这篇文章讲述了 ...