简洁明了的插值音频重采样算法例子 (附完整C代码…
2018-06-17 20:57:52来源:未知 阅读 ()
近一段时间在图像算法以及音频算法之间来回游走。
经常有一些需求,需要将音频进行采样转码处理。
现有的知名开源库,诸如: webrtc , sox等,
代码阅读起来实在闹心。
而音频重采样其实也就是插值算法。
与图像方面的插值算法没有太大的区别。
基于双线性插值的思路。
博主简单实现一个简洁的重采样算法,
用在对采样音质要求不高的情况下,也是够用了。
编解码库采用dr_wav
https://github.com/mackron/dr_libs/blob/master/dr_wav.h
近期有点强迫症,纯c实现。
贴上完整代码:
#ifdef __cplusplus extern "C" { #endif #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stdint.h> //采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码 #define DR_WAV_IMPLEMENTATION #include "dr_wav.h" void resampler(char *in_file, char *out_file); //写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 = (drwav_uint32) 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); if (samplesWritten != totalSampleCount) { fprintf(stderr, "ERROR\n"); exit(1); } } } //读取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'; } } void resampleData(const int16_t *sourceData, int32_t sampleRate, uint32_t srcSize, int16_t *destinationData, int32_t newSampleRate) { if (sampleRate == newSampleRate) { memcpy(destinationData, sourceData, srcSize * sizeof(int16_t)); return; } uint32_t last_pos = srcSize - 1; uint32_t dstSize = (uint32_t) (srcSize * ((float) newSampleRate / sampleRate)); for (uint32_t idx = 0; idx < dstSize; idx++) { float index = ((float) idx * sampleRate) / (newSampleRate); uint32_t p1 = (uint32_t) index; float coef = index - p1; uint32_t p2 = (p1 == last_pos) ? last_pos : p1 + 1; destinationData[idx] = (int16_t) ((1.0f - coef) * sourceData[p1] + coef * sourceData[p2]); } } void resampler(char *in_file, char *out_file) { //音频采样率 uint32_t in_sampleRate = 0; //总音频采样数 uint64_t totalSampleCount = 0; int16_t *data_in = wavRead_int16(in_file, &in_sampleRate, &totalSampleCount); uint32_t out_sampleRate = in_sampleRate * 2; uint32_t out_size = (uint32_t) (totalSampleCount * ((float) out_sampleRate / in_sampleRate)); int16_t *data_out = (int16_t *) malloc(out_size * sizeof(int16_t)); //如果加载成功 if (data_in != NULL && data_out != NULL) { resampleData(data_in, in_sampleRate, (uint32_t) totalSampleCount, data_out, out_sampleRate); wavWrite_int16(out_file, data_out, out_sampleRate, (uint32_t) out_size); free(data_in); free(data_out); } else { if (data_in) free(data_in); if (data_out) free(data_out); } } int main(int argc, char *argv[]) { printf("Audio Processing\n"); printf("博客:http://cpuimage.cnblogs.com/\n"); printf("音频插值重采样\n"); if (argc < 2) return -1; char *in_file = argv[1]; 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); resampler(in_file, out_file); getchar(); printf("按任意键退出程序 \n"); return 0; } #ifdef __cplusplus } #endif
不多注释,代码比较简单,一看就明了。
示例具体流程为:
加载wav(拖放wav文件到可执行文件上)->重采样为原采样的2倍->保存wav
若有其他相关问题或者需求也可以邮件联系俺探讨。
邮箱地址是:
gaozhihan@vip.qq.com
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 指针与const 2018-12-04
- c++学习笔记(一) 2018-08-10
- 洛谷P2765 魔术球问题(贪心 最大流) 2018-07-23
- C#下解决DrawImage画出来的Image变大了的问题 2018-06-18
- 最简洁的跨线程控件调用 2018-06-18
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash