高调音频变声原理 附简单示例代码

有关音频变声算法,这个是一个博人专门感谢兴趣之话题。

众人所熟悉的图像方面的3A算法来:

本来为发生众多开源算法可以参照学习,有因时域,也发出根据频域的算法。

AF自动对焦(Automatic Focus)
自行对焦即调节摄像头焦距自动获得清晰的图像的长河

最后算法想如果达的目的是均等。

AE自动曝光(Automatic Exposure)
活动曝光的是为着使感光器件获得适当的曝光量

近日吧生无数网友提问过关于变声算法的局部细节问题,邮件询问自己。

AW自动白平衡(Automatic White Balance)
白平衡的实质是如果白色物体在任何光源下都来得白色

要是叫来一个比较合理或者说通俗易懂的诠释,看似简单,其实还百般难的。

 

仍大概的一个逻辑思路,稍微理一料理,所以这个主题必须长“大话”这个前缀。

及之并行呼应的韵律方面的3A算法是:

也不打算讲特别深的,当然也是因出口不来。

AGC自动增益补偿(Automatic Gain Control)
自动调麦克风的收音量,使与会者收到一定的轻重水平,不见面为发言者与麦克风的离改变时,声音发出忽大忽小声的缺陷。

的于图像算法领域,非常重大的算法是高斯模糊,

ANS背景噪音抑制(Automatic Noise Suppression)
探测出背景固定频率之杂音并排除背景噪音。

当也可以认为是卷积,高斯模糊是卷积的一模一样种特例,这里虽无进行了。

AEC是回声消除器(Acoustic Echo Canceller)
本着扬声器信号及由它来的多路径回声的相关性为根基,建立远端信号的口音模型,利用其对回声进行估算,并不止地修改滤波器的系数,使得估计值更加逼近真实的回响。然后,将回声估计值从话筒的输入信号中减去,从而达到消除回声的目的,AEC还用话筒的输入与扬声器过去的价值相较,从而免去延长延迟的累反光的声学回声。根椐存储器存放的千古的喇叭的输出值的微,AEC可以排除各种延迟的回响。

假使之被音频,也许你呢猜测到了,基于时间的,毫无疑问,就是重复采样算法。

 

节奏采样率是赖录音设备以同秒钟内对声音信号的采样次数,

 图像方面的算法就不多说了,图像方面的3a算法,本人还实现了。

采样频率越来越强声音的回复就是逾真实更自然。

电动白平衡的关键思路,就是怎判定图像是否偏色,偏色后怎样修复的题目。

当当今的主流采集卡上,采样频率一般并分为22.05KHz、44.1KHz、48KHz三单等级,

科普的起直方图均衡,自动对比度,自动色阶等等。

22.05KHz只能达到FM广播的音品质,

机动曝光也是只要开曝光评估,常见的发生gama调节等等。

44.1KHz则是理论及之CD音质界限,48KHz则更可靠一些。

累有时间,再交叉贴起相应的代码。

看来此间,也许大多数丁要么无奈知道采样频率大约是呀意思。

在这边,先售个关子,占个坑。

换个角度来说吧,就是设一个总人口说“你好”,花了20毫秒,而机械当即时20毫秒内,

 

收集的数量稍就是可理解也采样率高低。

假若当节奏算法方面,自动增益补偿的算法有点类似图像的活动曝光算法。

也就是说,20毫秒内,采集到之数据量就是可以约认为目前之采样率,数据量越老,精度越来越强,采样率更是强。

关键要考虑的是多长的韵律,怎么分析当前节奏的音量或者强度。

那,我们重新变一个思路,想一个题材。

依据这强度对全体音频做一个归一化拉伸,诸如此类。

苟在同一的速率的气象下,

图像以及节奏殊途同归。

一个人口之语速快,一个人口之语速慢,那也或导致采样数据分布不雷同。

只要历史悠久的算法,莫过于,ReplayGain

此虽可以拓展一个板算法,就是变速。

ReplayGain是David
Robinson在2001年公布的平起建议规范,用于衡量计算机音频格式 中音频的响度。

啊,是的,就是变速。

有关的维基资料:

自打常理及来讲的话,其实变速就是在同等的采样率环境下,对采样数据进行拉伸或裁减。

https://en.wikipedia.org/wiki/ReplayGain

由算法的角度达的话吧,可以看是插值或抽值。

现今多数底板播放器都支持这特性。

而你吃一个丁提的快慢变得还快怎么开,

依据维基上之证实,现在大部分动的开源实现是 
MP3Gain

挺显著,就是当同样的采样率下,抽掉一些样书。

资料见:

相反,降速则是插一些样本。

http://wiki.hydrogenaud.io/index.php?title=Replaygain#Players_support

终极决定变速效果的就是是插样本与抽离样本的权重计算。

开源项目地址:

比如原来采样到之数是

http://mp3gain.sourceforge.net/

1234

色是C代码,非常干净。

增速的下,抽离样本 1 及 4

着重的算法实现文件见:gain_analysis.h 与 gain_analysis.c

23

算法是依据传入的板数据,分析需要进行增益的分贝值。

降速的早晚,增加样本 

匪欲增益则也0,需要增益则也相应的浮点正数或负数。

11223344

当然,不能够传播太少的板样本,否则无法客观剖析。

自只是举个例,便于大家了解这定义逻辑。

算法就待传入音频的数额和点名要分析的范本长度即可。

视此,肯定有人会问,

末段输出一个 推荐增益的分贝值。

这就是说声之尺寸也?或者说信号的强弱也?

依据这个分贝值进行折算,即好针对目标音频做有特定的节奏处理。

事实上也就是晋升音量和下降音量,我思念这理应不要解释。

 

变速是时域变,空间不换。

贴上整体的C代码:

如高低则恰恰相反,时域不更换,空间更换。

#ifdef __cplusplus
extern "C" {
#endif


#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"
#include "gain_analysis.h"


#ifndef min
#define min(a, b)            (((a) < (b)) ? (a) : (b))
#endif

//读取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;
}


float getGaindB(int16_t *buffer, size_t totalSampleCount, int sampleRate, size_t analyzeSamples) {
    float ret = -0.00000000001f;
    if (totalSampleCount == 0) return ret;
    if (analyzeSamples == 0) return ret;
    const int maxSamples = 2400;
    analyzeSamples = min(maxSamples, analyzeSamples);
    ret = 1.0f;
    int num_channels = 1;
    Float_t inf_buffer[maxSamples];
    size_t totalCount = totalSampleCount / analyzeSamples;
    if (InitGainAnalysis(sampleRate) == INIT_GAIN_ANALYSIS_OK) {
        int16_t *input = buffer;
        for (int i = 0; i < totalCount; i++) {
            for (int n = 0; n < analyzeSamples; n++) {
                inf_buffer[n] = input[n];
            }
            if (AnalyzeSamples(inf_buffer, NULL, analyzeSamples, num_channels) != GAIN_ANALYSIS_OK)
                break;
            GetTitleGain();
            //    printf("Recommended dB change for analyzeSamples %d: %+6.2f dB\n", i, titleGain);
            input += analyzeSamples;
        }
        ret = GetAlbumGain();
    }
    if ((int) ret == GAIN_NOT_ENOUGH_SAMPLES) {
        ret = -0.00000000001f;
    }
    return ret;
}


void analyze(char *in_file, int ref_ms) {
    uint32_t sampleRate = 0;
    uint64_t totalSampleCount = 0;
    int16_t *wavBuffer = wavRead_int16(in_file, &sampleRate, &totalSampleCount);
    if (wavBuffer != NULL) {
        size_t analyzeSamples = ref_ms * (sampleRate / 1000);
        float gain = getGaindB(wavBuffer, totalSampleCount, sampleRate, analyzeSamples);

        printf("recommended dB change: %f \n", gain);
        free(wavBuffer);
    }
}

int main(int argc, char *argv[]) {
    printf("Replay Gain Analysis\n");
    printf("blog:http://cpuimage.cnblogs.com/\n");
    printf("e-mail:gaozhihan@vip.qq.com\n");
    if (argc < 2)
        return -1;
    char *in_file = argv[1];
    //指定分析长度1秒
    int ref_ms = 1000;
    analyze(in_file, ref_ms);
    getchar();
    printf("press any key to exit. \n");
    return 0;
}

#ifdef __cplusplus
}
#endif

可省略粗暴地领略,就是线性拉伸。

自家之惯,尽量少把注释,代码尽量干净整洁。

诸如原来采样到之数额是

于是大家一直看代码吧。

1234

类型地址:https://github.com/cpuimage/ReplayGainAnalysis

每个样本+4,直接拉伸为

 

5678

示范具体流程也:

否产生应用乘法进行拉伸的,

加载wav(拖放wav文件及可执行文件上)->输出结果->保存wav

例如 乘以2

 

2468

抱相应的评估结果随后,接下作何处理,就看各位看官的求实需要了。

地方是增大音量,降低音量反的便是削弱和除。

 

比方最后不管变速还是音量调节,

若发生其他相关题材或要求也得以邮件联系个人探讨。

末尾算法要召开的事务就是是规定对诺位置的对应权重。

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

理所当然为要拘留最后想要达成什么的效用,适配权重。

 

即了这般一特别圈,还是没有说及变声的问题。

实则,变声就是变速+音量调节。

如上变速也好,音量调节可,相对而言都是线性拉伸,

直的加减乘除然后插值抽值就会上的。

假如变声的定义其实呢是相仿之,

哪怕当以同样时域内又调节对应时域的音量权重。

换言之便是于同一个采样率内,同时决定语速和音量在一个一定的权重内。

其实就是一个时域和空间的二维拉伸。

略知一二这逻辑确实来硌绕。

故而采样算法来举行一个简单的以身作则。

参考前面的章《简洁明了的插值音频重采样算法例子
(附完整C代码)》

本条示例中之采样函数是:

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);
    }
}

叫咱有些变通一下,设一个采样速率,用来调节声音之速度,同时确保采样率不移。

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);
    float speed = 0.88;//增加一个速度权重
    uint32_t out_sampleRate = in_sampleRate * speed;
    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);
        //out_sampleRate改为输出一样的采样率in_sampleRate
        wavWrite_int16(out_file, data_out, in_sampleRate, (uint32_t) out_size);
        free(data_in);
        free(data_out);
    } else {
        if (data_in) free(data_in);
        if (data_out) free(data_out);
    }
}

修改后是以此法的。

来胸的爱侣发现了。out_size数值有或叠加或缩小了。

以上示例代码,就是一个简便的变速算法。

变速就是如此一个规律,音量增大降低就未开示范了。

比方变声是一个啊算法也?

说白了,就是变速的还要保证out_size还是本来的totalSampleCount。

那使怎么确保为?

答案就是插值,如果简单粗暴一点,补0或者删0即可。

自如此做吧,可能会见招致音量不一样,最终发声不对的情事。

当即终将是不正确的,最终的插值时候的权重和对应之始末,产生的效力即使扣留各家本领了。

上述原理,也说得几近了,具体怎么落实的话,

世家自行参阅相关的开源代码,再夺领悟一下。

此外说一下前方《声音变调算法PitchShift(模拟汤姆猫)
附完整C++算法实现代码》

即时篇稿子中之sin和cos 没有在使得距离内,所以fastsin
fastcos计算的结果是发题目的。

端详大家还是参阅作者原算法吧。

本,后面来时空我会放出,

简言之清晰的变声算法的整c代码和相应之演示代码。

一旦至于因傅里叶变换的重采样算法,《基于傅里叶变换的音频重采样算法
(附完整c代码)》%E3%80%8B)

当对应之github
项目fftResample达,我吧开了算法逻辑上之更正。

刊过之章一般大少进行次不良编辑了,

至于后期的有的修正和改动,大家还是关心一下github项目的创新比较一直一点。

切实变声的实现原理,

总的看,希望经过这篇稿子,

世家对旋律变声算法能出于直观的掌握与认识。

上述,权当抛砖引玉。

独乐乐不如一起娱乐。

苟有其它有关问题或需要吗足以邮件联系我探讨。

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

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图