Pure Data Rosenberg波 声帯音源波のパッチ
はじめまして。最近、Unityに手を出そうとしているPureDataユーザーの真城亜です。今回はPureDataでRosenberg波(声帯音源波)を作成してみます。
まずRosenberg波とはなにかですが、人間の声のしくみを再現するうえで重要な音声信号で、声帯から発せられているブザーのような音のことです。
そもそも、声はどうやって作られているのでしょう?皆さんは考えてみたことがありますでしょうか?
答えは、声帯と呼ばれる人間の喉にある器官を呼気が通るときに振動し、その振動によって作られた音を口(声道)で加工(調音)することで作られます。
そして、今回のプログラムは人間の声道をシミュレーションする波形を作るプログラムです(関連項目 声道の音響管モデル)。
では、今回のソースコードを記載します。空っぽのpuredata patchを保存してからテキストエディタで開いて、以下のテキストをコピーしてペーストして保存します。画像の左側のパッチのソースコードです。
#N canvas 1163 153 703 732 12;
#X obj 250 36 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 250 60 t b b;
#X msg 173 102 511 0 \, 1 513 \, 2 514;
#X obj 173 132 unpack;
#X obj 173 163 tabread rosenberg;
#X obj 173 199 tabwrite rosenberg;
#N canvas 0 50 450 250 (subpatch) 0;
#X array rosenberg 515 float 2;
#X coords 0 1 515 -1 200 140 1;
#X restore 106 269 graph;
#X msg 366 79 512;
#X obj 366 108 until;
#X obj 366 135 f 0;
#X obj 366 166 + 1;
#X obj 366 198 t f f;
#X obj 366 449 tabwrite rosenberg;
#X obj 366 330 expr 3*pow($f1/205 \, 2)-2*pow($f1/205 \, 3);
#X obj 486 395 * 0;
#X obj 366 229 moses 206;
#X obj 426 259 moses 288;
#X obj 426 364 expr 1-pow(($f1-205)/82 \, 2);
#X text 82 512 3*pow(t/t1 \, 2)-2*pow(t/t1 \, 3) 0 <= t <= t1;
#X text 81 572 0 t > t1+t2;
#X text 81 543 1-pow((t-t1)/t2 \, 2) t1 <= t <= t1+t2;
#X text 83 615 t1 = 0.4t \, t2 = 0.16t;
#X text 84 661 512*0.4=204.8 = 205 \, 512*0.16=81.92 = 82 \, 205+82
= 287;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 1 1 7 0;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 3 1 5 1;
#X connect 4 0 5 0;
#X connect 7 0 8 0;
#X connect 8 0 9 0;
#X connect 9 0 10 0;
#X connect 10 0 9 1;
#X connect 10 0 11 0;
#X connect 11 0 15 0;
#X connect 11 1 12 1;
#X connect 13 0 12 0;
#X connect 14 0 12 0;
#X connect 15 0 13 0;
#X connect 15 1 16 0;
#X connect 16 0 17 0;
#X connect 16 1 14 0;
#X connect 17 0 12 0;
すると、冒頭の画像の通りになるはずです。ならなかったら、画像のようにプログラムしてください。冒頭の画像をもう一度載せます。
ではプログラムの解説です。
Rosenberg波は数式で算出できます。数式は以下のリンク先ページでPDFをダウンロードすると確認できます。「音源波形の違いが電気喉頭音声に与える影響の検討」https://www.jstage.jst.go.jp/article/prociiae/2013/0/2013_24/_article/-char/ja/
まず先ほどの画像の左側を中心に解説していきます(画像の右側と左側ではほぼ同じことをやっています)。解説は以下のリンク先のドキュメントを基に記述します。こちらのドキュメントにも同じ数式が出てきます。(リンク先、「ローゼンバーグ波 (Rosenberg wave)」の項目のPDFを参照)
T1と書かれた部分がありますね。これは 波形の上がる部分の長さです。次に、T2と書かれた部分は、波形の下がる部分の長さです。そして、T1とT2を合わせた部分が声道が開いている時間となります。波形の右半分、グラフ(PuredataではArrayと言います)のY軸方向で中央を示している部分(=0)は声道が閉じている時間です。なお、声道が閉じている時間はT1+T2の時間長以上の時だけになります。声道が開いて閉じるまでが一周期で、周波数が440Hzの時は、1秒間に440サイクル振動することになります。
T1及びT2の値は合計で1未満を推奨します(でないと声道が開きっぱなしになります)。
数式の通りにexpr~(expression)オブジェクト(0~1までを繰り返す、のこぎり波を基に作成するのでチルダオブジェクトです)に入力します。powの引数の仕様に注意です。「Expr family objects by Shahrokh Yadegari」を参考にしてください。
http://yadegari.org/expr/expr.html
T1とT2の数値を変えると、音が変化します。
Rosenberg波を基に加工していくと、音声合成ができると思います。
解説は以上となります。
あとがき
なぜのこぎり波(phasor~オブジェクト)を使ったかというと、0~1までカウントする & 音声を出力できるからです。右側について解説すると、右側はwabetable合成のためのプログラムで、波形の総sample数が515で作られています。wavetableは一度作れば、使うたびにストレージから読み込むだけでいいので便利です。そのために、Rosenberg波のwavetableを作るためのパッチも記載しました。やっていることは同じです。
蛇足です。VSTシンセプラグインにSurgeというものがあるのですが、SurgeのFormant parameterは今回のプログラムの声道を閉じる部分と同じような気がします。以上です。
最後に、紹介したページ制作者様と、「音響入門シリーズA-1 音響学入門」の執筆者の方々、twitterでRosenberg波を教えてくださったとあるプログラマの方(現在はtwitterを辞められてしまいました)と、今回のアルゴリズムを考案された方(A. E. Rosenberg)に感謝申し上げます。
参考文献
コロナ社 日本音響学会 編「音響入門シリーズA-1 音響学入門」
屏 貴文, 田中 裕人, 水町 光徳, 中藤 良久, 松井 謙二「音源波形の違いが電気喉頭音声に与える影響の検討」
http://shinngoushori.com/speechinformationprocessing/ 「ローゼンバーグ波 (Rosenberg wave)」
Shahrokh Yadegari「Expr family objects by Shahrokh Yadegari」
A. E. Rosenberg (1971) "Effect of Glottal Pulse Shape on the Quality of Natural Vowels"
この記事が気に入ったらサポートをしてみませんか?
コメント