您的位置:首页 > 编程语言 > C语言/C++

分享用于学习C++音频处理的代码示例

2018-01-13 10:49 645 查看
与《分享用于学习C++图像处理的代码示例》为姊妹篇。

为了便于学习C++音频处理并研究音频算法,

俺写了一个适合初学者学习的小小框架。

麻雀虽小五脏俱全,仅仅考虑单通道处理。

采用Decoder and Encoder:dr_wav
https://github.com/mackron/dr_libs/blob/master/dr_wav.h
关于wav格式的解析移步至:
http://soundfile.sapp.org/doc/WaveFormat/


个人习惯,采用int16的处理方式,也可以通过简单的修改,改为float类型。

wav音频样本可以从维基百科上(https://en.wikipedia.org/wiki/WAV)下载。

注:少数wav格式不支持

FormatBitrate (kbit/s)1 minute (KiB)Sample
11,025 Hz 16 bit PCM176.4129211k16bitpcm.wav
8,000 Hz 16 bit PCM1289388k16bitpcm.wav
11,025 Hz 8 bit PCM88.264611k8bitpcm.wav
11,025 Hz µ-Law88.264611kulaw.wav
8,000 Hz 8 bit PCM644698k8bitpcm.wav
8,000 Hz µ-Law644698kulaw.wav
11,025 Hz 4 bit ADPCM44.132311kadpcm.wav
8,000 Hz 4 bit ADPCM322348kadpcm.wav
11,025 Hz GSM 06.101813211kgsm.wav
8,000 Hz MP3 16 kbit/s161178kmp316.wav
8,000 Hz GSM 06.10131038kgsm.wav
8,000 Hz Lernout & Hauspie SBC 12 kbit/s12888ksbc12.wav
8,000 Hz DSP Group Truespeech9668ktruespeech.wav
8,000 Hz MP3 8 kbit/s8608kmp38.wav
8,000 Hz Lernout & Hauspie CELP4.8358kcelp.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();
return (fn(), took + now()) / 1000;
}

//写wav文件
void wavWrite_int16(char* filename, int16_t* buffer, int sampleRate, uint32_t totalSampleCount) {
drwav_data_format format;
format.container = drwav_container_riff;     // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
format.format = DR_WAVE_FORMAT_PCM;          // <-- Any of the DR_WAVE_FORMAT_* codes.
format.channels = 1;
format.sampleRate = sampleRate;
format.bitsPerSample = 16;
drwav* pWav = drwav_open_file_write(filename, &format);
if (pWav)
{
drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);
drwav_uninit(pWav);
}
}
//读取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;
}

//分割路径函数
void splitpath(const char* path, char* drv, char* dir, char* name, char* ext)
{
const char* end;
const char* p;
const char* s;
if (path[0] && path[1] == ':') {
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;

if (argc < 2) return -1;
char* in_file = argv[1];

//音频采样率
uint32_t sampleRate = 0;
//总音频采样数
uint64_t totalSampleCount = 0;
int16_t* wavBuffer = NULL;
double nLoadTime = bench([&]
{
wavBuffer = wavRead_int16(in_file, &sampleRate, &totalSampleCount);
});
std::cout << " 加载耗时: " << int(nLoadTime * 1000) << " 毫秒" << std::endl;

//如果加载成功
if (wavBuffer != NULL)
{
//将前面一般进行静音处理,直接置零即可
for (uint64_t i = 0; i < totalSampleCount / 2; i++)
{
wavBuffer[i] = 0;
}
}
//保存结果
double nSaveTime = bench([&]
{
char drive[3];
char dir[256];
char fname[256];
char ext[256];
char out_file[1024];
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 << " 保存耗时: " << int(nSaveTime * 1000) << " 毫秒" << std::endl;
if (wavBuffer)
{
free(wavBuffer);
}
getchar();
std::cout << "按任意键退出程序 \n" << std::endl;
return 0;
}


示例具体流程为:

加载wav(拖放wav文件到可执行文件上)->简单静音处理->保存wav

并对 加载,保存 这2个环节都进行了耗时计算并输出。

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

邮箱地址是:
gaozhihan@vip.qq.com

若此博文能帮到您,欢迎扫码小额赞助。

微信:



支付宝:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: