前面说起到《大话音频变声原理 附简单示例代码》与《声音变调算法PitchShift(模拟汤姆猫) 附完整C++算法实现代码》html
都稍微讲过变声的原理和具体实现。python
你们都知道,算法从实现到最后工程应用,中间的环节和问题特别多。c++
尤为是编码的架构设计,好的数据结构和代码逻辑封装确定是可复用,组件化的。git
前几天写完《音频识别算法思考与阶段性小结》的时候,github
我也说起到了。算法
会作一些算法编码优化相关的分享。编程
而有时候我总以为文字表达很苍白,c#
因此我尽量地把代码写得简洁易懂,数据结构
一方面是便于基础差的朋友学习。架构
另外一方面也是为了本身在编码以及思考的时候,能更加清晰。
固然,变声算法绝大多数朋友都会选择一些开源的或者商业sdk去作二次开发。
例如:
https://www.surina.net/soundtouch/
但若是仅仅停留在使用的阶段,它就是一个黑盒子。
知其然,殊不知其因此然。
是远远不够的。
有时候咱们是要站在巨人的肩膀上去看到更美丽的风景。
可是,我但愿是一群人,而不是一我的。
也许你们也发现了,我写的大多数算法,是纯c无第三方依赖的。
是否是就会怀疑,我就只会写c语言?
不是的,我所掌握的编程语言:
主要: c,c++,python,汇编
其次:pascal,c#,js,lua,go等
编程语言只是一个工具,关键仍是算法思路。
用纯c写的主要目的,是为了破除一些第三方依赖,
不要只知其一;不知其二地使用黑盒子。
固然,其次的好处就是跨平台,便携,可复用。
这样,一切了然于心。
为何不能够造轮子呢?
只要你造的轮子是有用的,
无论是用于观赏用于学习仍是其余用途。
在我了解到一些音频算法的思路以后,
变声算法的思路,
我以为它的思路很是适用于扩展到大多数音频算法实现,
并且可复用度比较高。
因此,将它梳理开源,就显得特别有意义。
而你们能够基于这个实现,进一步去改进或者学习 音频算法,
例如降噪,增益等等。
由于这个编码实现的设计是彻底能够适用到音频算法应用场景的。
逻辑也很是清晰。
项目地址:
https://github.com/cpuimage/pitchshift
固然为了便于一些朋友的学习使用,
示例代码提供一个简易的实现,
模拟变声为小黄人。
int main(int argc, char *argv[]) { printf("Audio Processing \n"); printf("blog:http://cpuimage.cnblogs.com/ \n"); printf("Pitch Shifting Using The Fourier Transform\n"); if (argc < 2) return -1; char *in_file = argv[1]; uint32_t sampleRate = 0; uint64_t totalSampleCount = 0; uint32_t channels = 0; short *data_in = wavRead_s16(in_file, &sampleRate, &totalSampleCount, &channels); if (data_in != NULL) { float pitchShift = 0.9f; size_t ms = 50; size_t overSampling = 4; size_t frameSize = sampleRate * ms / 1000; frameSize += frameSize % 2; planData pitchPlanData = {0}; double startTime = now(); makePlanData(frameSize, overSampling, sampleRate, &pitchPlanData); pitchshift(pitchShift, data_in, data_in, totalSampleCount, &pitchPlanData); // turn to minion pitch { totalSampleCount /= 2; short *samples = data_in; for (int i = 0; i < totalSampleCount; i++) { data_in[i] = samples[0]; samples += 2; } } double time_interval = calcElapsed(startTime, now()); freePlanData(&pitchPlanData); printf("time interval: %f ms\n ", (time_interval * 1000)); } 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_s16(out_file, data_in, sampleRate, totalSampleCount); if (data_in) { free(data_in); } printf("press any key to exit.\n"); getchar(); return 0; }
不作多解释,你们能够参阅pitchshift函数的实现,
主要实现位于文件PitchShift.h。
整个算法不到200行,逻辑很是清晰,
已经作了必定程度上的工程化优化。
固然还有很大的改进空间,
不过这份代码,更多的意义在于学习。
授人以鱼不如授人以渔。
如有其余相关问题或者需求也能够邮件联系俺探讨。
邮箱地址是: gaozhihan@vip.qq.com