大話音頻變聲原理 附簡單範例程式碼

來源:互聯網
上載者:User

關於音頻變聲演算法,這個是一個很多人特別感興趣的話題。

當然也有不少開源演算法可以參閱學習,有基於時域,也有基於頻域的演算法。

最終演算法想要達到的目的是一致。

最近也有不少網友問過關於變聲演算法的一些細節問題,郵件詢問我。

要給出一個比較合理或者說通俗易懂的解釋,看似簡單,其實還蠻難的。

按照大概的一個邏輯思路,稍微理一理,所以這個主題必須加上“大話”這個首碼。

也不打算講特別高深的,當然也是因為講不來。

之於映像演算法領域,非常重要的演算法是高斯模糊,

當然也可以認為是卷積,高斯模糊是卷積的一種特例,這裡就不展開了。

而之於音頻,也許你也猜到了,基於時間的,毫無疑問,就是重採樣演算法。

音頻採樣率是指錄音裝置在一秒鐘內對聲音訊號的採樣次數,

採樣頻率越高聲音的還原就越真實越自然。

在當今的主流採集卡上,採樣頻率一般共分為22.05KHz、44.1KHz、48KHz三個等級,

22.05KHz只能達到FM廣播的聲音品質,

44.1KHz則是理論上的CD音質界限,48KHz則更加精確一些。

看到這裡,也許大多數人還是沒法理解採樣頻率大概是什麼意思。

換個角度來說的話,就是假設一個人說“你好”,花了20毫秒,而機器在這20毫秒內,

採集的資料多少就可以理解為採樣率高低。

也就是說,20毫秒內,採集到的資料量就是可以大概認為目前的採樣率,資料量越大,精度越高,採樣率越高。

那麼,我們再換一個思路,想一個問題。

如果在同樣的速率的情況下,

一個人的語速快,一個人的語速慢,那也可能造成採樣資料分布不一致。

這裡就可以展開一個音頻演算法,就是變速。

嗯,是的,就是變速。

從原理上來講的話,其實變速就是在同樣的採樣率環境下,對採樣資料進行展開或壓縮。

從演算法的角度上來說的話,可以認為是插值或抽值。

如果你讓一個人講話的速度變得更快怎麼做,

很明顯,就是在同樣的採樣率下,抽掉一些樣本。

反之,降速則是插入一些樣本。

最終決定變速效果的就是插入樣本和抽離樣本的權重計算。

例如原來採樣到的資料是

1234

加速的時候,抽離樣本 1 和 4

23

降速的時候,增加樣本 

11223344

當然只是舉個例子,便於大家理解這個概念邏輯。

看到這裡,肯定有人會問,

那聲音的大小呢?或者說訊號的強弱呢?

其實也就是提升音量和降低音量,我想這個應該不用解釋。

變速是時域變,空間不變。

而音量則反之,時域不變,空間變。

可以簡單粗暴地理解,就是線性展開。

例如原來採樣到的資料是

1234

每個樣本+4,直接展開為

5678

也有採用乘法進行展開的,

例如 乘以2

2468

上面是增大音量,降低音量反之就是減和除。

而最終不管變速還是音量大小,

最終演算法要做的事情就是確定對應位置的對應權重。

當然也要看最終想要達到什麼樣的效果,適配權重。

饒了這麼一大圈,還是沒有說到變聲的問題。

其實,變聲就是變速+音量大小。

以上變速也好,音量大小也好,相對而言都是線性展開,

直接的加減乘除然後插值抽值就能達到的。

而變聲的概念其實也是類似的,

就是在在同一時域內同時調節對應時域的音量權重。

換言之就是在同一個採樣率內,同時控制語速和音量在一個特定的權重內。

其實就是一個時域和空間的二維展開。

理解這個邏輯確實有點繞。

用採樣演算法來做一個簡單的樣本。

參閱前面的文章《簡潔明了的插值音頻重採樣演算法例子 (附完整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代碼)》

在對應的github 項目fftResample上,我也做了演算法邏輯上的修正。

發表過的文章一般很少進行二次編輯了,

關於後期的一些修正和變更,大家還是關注一下github項目的更新比較直接一點。

具體變聲的實現原理,

如上所述,希望通過這篇文章,

大家對音頻變聲演算法能有比較直觀的理解和認識。

以上,權當拋磚引玉。

獨樂樂不如一起玩樂。

若有其他相關問題或者需求也可以郵件聯絡俺探討。

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

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.