ピッチシフトについてメモ

音声データを再生するときに早送りにしたり、ゆっくり再生すると声が高くなったり低くなったりする。
再生するスピードを変えずに声の高さだけを変えることをピッチシフトと言うらしい。

やり方はいろいろあるようで、音声データを短い時間に区切って間引いたり、かさ増ししたりして音データをつなげなおすと音程が変わる方法や、フーリエ変換で音の周波数を求め、周波数を変更して逆フーリエ変換で戻してやる方法があるようだ。

Androboiceではとりあえず間引いたりかさ増しする方法で実現している。

音を1オクターブ高くするには周波数を2倍にすればよいらしい。だから短い時間に区切って音データを半分に間引いて、間引いたデータを区切ったデータの後ろにくっつけて長さを同じにする。それを全てのデータ分実行すると再生速度そのままで1オクターブ高い音が作れる。

0,1,2,3,4,5,6,7,8,9
を
0,2,4,6,8,0,2,4,6,8
にする

これで2倍の高さの音になる。

この「0,1,2,3,4,5,6,7,8,9」って音の幅はどれくらいかというと8000Hzで約33msec分で240サンプル分を間引き処理してつなげている。

0,1,2,3,4,5,6 .....237,238,239,    240,241,242,243, ... 7998,7999
これを
0,2,4,6, ... 236,238,0,2,4,6, ... 236,238,      240,242,244, ... 7996,7998
こんな具合で1秒間の処理おわり

238と240のつなぎ目は滑らかにならないので雑音のようになるのだが、なめらかにする処理は省略した。分からないので。

なぜ30msecで区切ることにしたのかというと、自分の声を録音して波形編集ソフトで変換してみて、大体30msecくらいならうまくいくかなーと思ったから。人の声は大体300Hzくらいなので1秒間に300回なんらかの波が繰り返されていることになる。んで30msecなら6回から10回くらい繰り返しているので、「これなら加工しやすいだろう」となんとなく感覚で決めた。

まあ、waveデータを加工して音作りをしている人にとっては大したことないのかもしれないが、良い勉強になった。

フーリエ変換バージョンもあるのだが、1秒の音を変換するのに9秒くらいかかってしまう。これではFFTとは言えないくらい遅い。
floatの配列を使って演算しているのだが、これがボトルネックなのだろう。FixPointで計算するかJNIを使うしかないかもしれない。
また勉強することが増えた。

Related posts:

  1. Androidで音声処理3
  2. Androidで音声処理1
  3. Androidで音声処理2

関連記事はYARPP関連記事プラグインによって表示されています。