音频算法之小黄人变声 附完整C代码

前面说起到《大话音频变声原理 附简单示例代码》与《声音变调算法PitchShift(模拟汤姆猫) 附完整C++算法实现代码html

都稍微讲过变声的原理和具体实现。python

你们都知道,算法从实现到最后工程应用,中间的环节和问题特别多。c++

尤为是编码的架构设计,好的数据结构和代码逻辑封装确定是可复用,组件化的。git

前几天写完《音频识别算法思考与阶段性小结》的时候,github

我也说起到了。算法

会作一些算法编码优化相关的分享。编程

而有时候我总以为文字表达很苍白,c#

因此我尽量地把代码写得简洁易懂,数据结构

一方面是便于基础差的朋友学习。架构

另外一方面也是为了本身在编码以及思考的时候,能更加清晰。

固然,变声算法绝大多数朋友都会选择一些开源的或者商业sdk去作二次开发。

例如:

https://www.fmod.com/

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

相关文章
相关标签/搜索