8月はなぜか毎年本業がとても忙しく、ここ1ヶ月ハンダゴテを使っていません。かなりストレスがたまってきたので、ソフトでちょこっと遊んでみました。
C++ で大雑把に書いていたボコーダのプログラムを少し整理、C で書き直して、さらに色んなプラットフォームにのせやすいようにメモリ管理まわりをちゃんと設計してみました。
ボコーダの心臓部のプログラムをちょびっと公開。線形予測分析+合成フィルタ、以上。コーデックとして作るとかなり難しいですが、楽器だとあえていい加減に作ってかまわないので、拍子抜けするほど簡単です。
そのうちきちんと公開したいと思います。(ああ、もうこんな時間。寝なくては)
/**
* vocoder
* The vocoder process.
* Note: The voice input will be changed by this function. (because of hann())
*/
void
vocoder(Processor* processor,
float voice[], float excit[], float out[])
{
/* temporal buffers */
float* corr;
float* lpc;
float* ref;
/* parameters */
register int frameSize, np, ip, ismp;
float ratio, level, power;
VocoderParameters* params;
/* fetch frequently-used parameters from the processor */
frameSize = processor->frameSize;
params = (VocoderParameters*)processor->parameters;
np = params->np;
/* get temporal beffer memory from the stack */
corr = (float*)stack_push(processor->stack, (np + 1) * sizeof(float));
lpc = (float*)stack_push(processor->stack, (np + 1) * sizeof(float));
ref = (float*)stack_push(processor->stack, (np + 1) * sizeof(float));
/* get the LPC coefficients */
power = hann(voice, frameSize);
autoCorrelate(frameSize, voice, np, corr);
ratio = levinsonRecursion(np, corr, lpc, ref);
#ifdef _DEBUG
vocoder_debug_print(corr, lpc, ref, ratio, np);
#endif
/* The synthesis filter. */
{
float* buf = params->outBuffer;
level = (float)(sqrt(power*ratio/frameSize) * 0.5f);
iir(frameSize, out, excit, ip, buf, lpc, level);
}
stack_pop(processor->stack, (np+1) * 3 * sizeof(float));
}
有声・無声判別はナシですね :)
私はダービン法と呼んでいましたが、そういえばレヴィンソン=ダービン アルゴリズムでしたね、と記事を読んで勝手に懐かしさに浸っておりまする。
その昔、LPCから極を求めて極座標にマッピングして、位置をずらして再合成したりして遊んでいました。
はいレビンソンダービン久しぶりに使ってすばらしさを再確認しました。
極ずらすのは LSP でも使うんですか?ボイスチェンジができますね。面白そう。挑戦してみようかな。
有声・無声判別はリハビリにはちょこっと重いです :-)
どっかに参考ソースコード落ちてないかな :-)
LSPではなくて、すなおにARモデルの分母をニュートン法で解いて求めた極をZ平面にプロットしました。
フィルタが発振していなければ単位円内に収まるはずの(ノルムをかえると不安定になるので)極の角度をくりくりと。
ただやみくもにやると音韻性が崩れるので、まえもってフォルマントのマッピングを学習しておいて、Aさんの声をBさんの声にする とかいういじり方でした。
おお、なるほど。そんなアプローチもあるのですね。フォルマントは単純な移動では壊れてしまいますか。マッピングを学習というところにノウハウが濃密に蓄積されていそうです。