いつもお世話になっています。
大学の課題でつまずいてしまったので、皆さんのお力をお借りしたく質問させていただきます。
今、wave形式の音声ファイルの加工プログラムを作成しています。
データ部の読み込みを以前は1バイトならunsigned char型、2バイトならshort型で読み込んでいたのですが、
これを、2バイトでもunsigned char型で読み込んでから、little endianの仕様に従い(?)
short型に変換して読み込むという方法に変えました。
1バイトの場合でも、途中の処理はshort型として扱っています。
この方法に変えてから、今まで作ってきた加工処理を行うと、思い通りの音声が生成されなくなりました。
今まで作ってきた加工処理は
・音を半分にする
・ステレオをモノラルに変換する
・倍速にする
というものです。
デバッグとして、各値をファイル出力してみてみると、どんな音声ファイルでも(16ビット)
iが2048以降はすべて同じ値になっているので、
どうもmain関数内のfread, fwriteあたりが怪しいと思っているのですが、
どこが間違っているのかが分かりません。
ブロックサイズは8192として扱っているので、16ビットの音声ファイルだと、
実質ブロックサイズは4096になっています。
このブロックサイズを変更すると、生成された音声ファイルの問題点が明白になるので、
ブロックサイズに依存しているようです。
ソースコードをアップしておきますので、どなたかご教授お願いします。
テストの音声ファイルは
・test16_s ステレオ 16ビット
・test16_m モノラル 16ビット
・test8_s ステレオ 8ビット
・test8_m モノラル 8ビット
となっています。
音声処理のプログラム
Re:音声処理のプログラム
>どこが間違っているのかが分かりません
・ 16bitの時の wave_data_trans()ですでに元バッファサイズの半分になった t_sizeで
ループを回しているのに、for文で i+=2をしているので処理が途中で終わってしまっており、
data_inの残りの部分が不定になっている。
・ 同様に wave_data_inv()もループの回数が足りない
・ write_flag == 1が常に trueなので、ループを通過する度にヘッダを書き込んでしまっている
こんなところじゃないでしょうか。
Re:音声処理のプログラム
>>Justyさん
>処理が途中で終わってしまっており
おっしゃる通りでした。
16ビットデータの時、変換後のブロックサイズに合わせてしまっていたので、
元のデータ後ろ半分が処理されていませんでした^^;
テキストデータで出力させてみると、2048以降が同じ数値だったので、
値が入れられていない(初期化になるんでしょうか?)のかな?とは睨んでいたのですが、
少し見当違いの個所をずっと修正していました。
おかげさまで、無事正常な音声ファイルが出力されるようになりました。
ありがとうございます。
もう一点だけ質問させてください。
音声を倍速かつ音(音声)が高くならないプログラムを作っているのですが、
(double_speed2関数です)
これがずっとうまくいきません。
ステレオであれば、正常な音声ファイルが出力されるのですが、
モノラルだと、変な音声ファイルが出力されています。
文章では説明しづらいので、プログラムを実行していただければ
何が問題であるのかご理解いただけると思います。
(無責任で申し訳ないです)
処理にフーリエ変換を使用しています。
dft_idft()とfft_ifft()には間違いはないと思います。
1周期分のsin波を上記2つの関数に渡したところ、正常に変換されています。
となると、周波数空間での加工部分、もしくは引数を渡す部分に間違いがある、
としか考えられません。
これもどこに問題があるのかが分かりませんorz
かれこれ1か月ほど悩んでいます。
修正版のソースをアップしておきますので、こちらの方もご教授お願いします。
>処理が途中で終わってしまっており
おっしゃる通りでした。
16ビットデータの時、変換後のブロックサイズに合わせてしまっていたので、
元のデータ後ろ半分が処理されていませんでした^^;
テキストデータで出力させてみると、2048以降が同じ数値だったので、
値が入れられていない(初期化になるんでしょうか?)のかな?とは睨んでいたのですが、
少し見当違いの個所をずっと修正していました。
おかげさまで、無事正常な音声ファイルが出力されるようになりました。
ありがとうございます。
もう一点だけ質問させてください。
音声を倍速かつ音(音声)が高くならないプログラムを作っているのですが、
(double_speed2関数です)
これがずっとうまくいきません。
ステレオであれば、正常な音声ファイルが出力されるのですが、
モノラルだと、変な音声ファイルが出力されています。
文章では説明しづらいので、プログラムを実行していただければ
何が問題であるのかご理解いただけると思います。
(無責任で申し訳ないです)
処理にフーリエ変換を使用しています。
dft_idft()とfft_ifft()には間違いはないと思います。
1周期分のsin波を上記2つの関数に渡したところ、正常に変換されています。
となると、周波数空間での加工部分、もしくは引数を渡す部分に間違いがある、
としか考えられません。
これもどこに問題があるのかが分かりませんorz
かれこれ1か月ほど悩んでいます。
修正版のソースをアップしておきますので、こちらの方もご教授お願いします。
Re:音声処理のプログラム
>こちらの方もご教授お願いします
いや、サウンド方面はさほど得意ってわけじゃないんですが・・・・・・。
でもまぁ、精度を気にしないのであれば加工の部分は
[color=#d0d0ff" face="monospace]
for(i=0; i<size/2; i++){
re = t_re[2*i];
im = t_im[2*i];
}
for(; i<size; i++){
re = 0;
im = 0;
}[/color]
でいいんじゃないのでしょうか?
ちゃんとやるなら
Pitch Shifting Using The Fourier Transform - The DSP Dimension
ttp://www.dspdimension.com/admin/pitch-shifting-using-the-ft/
とか
SoundTouch
ttp://www.surina.net/soundtouch/
を研究した方がいいかもしれません。
Re:音声処理のプログラム
>>Justyさん
ありがとうございます。
おかげで解決することができました^^
配列にはa[-10]みたいに負の数がないというのを忘れていました。
なので、コンピューター内と、実際に考える周波数空間の並び方が異なっているのですね。
>Pitch Shifting Using The Fourier Transform - The DSP Dimension
>ttp://www.dspdimension.com/admin/pitch-shifting-using-the-ft/
>SoundTouch
>ttp://www.surina.net/soundtouch/
せっかく教えていただいたので、こちらの方も研究して、
さらに良い処理ができるようにしてみたいと思います。
ちなみに
>for(; i<size; i++){
iの初期値が書かれていないですけど、
for(i=size/2, i<size, i++){
でいいのですよね?
ありがとうございます。
おかげで解決することができました^^
配列にはa[-10]みたいに負の数がないというのを忘れていました。
なので、コンピューター内と、実際に考える周波数空間の並び方が異なっているのですね。
>Pitch Shifting Using The Fourier Transform - The DSP Dimension
>ttp://www.dspdimension.com/admin/pitch-shifting-using-the-ft/
>SoundTouch
>ttp://www.surina.net/soundtouch/
せっかく教えていただいたので、こちらの方も研究して、
さらに良い処理ができるようにしてみたいと思います。
ちなみに
>for(; i<size; i++){
iの初期値が書かれていないですけど、
for(i=size/2, i<size, i++){
でいいのですよね?
Re:音声処理のプログラム
>iの初期値が書かれていないですけど、
>for(i=size/2, i<size, i++){
>でいいのですよね?
それでもいいですし、そのままでも大丈夫ですよ。
1つ上の forで使われた iの値をそのまま引き継いで使っていますから。
Re:音声処理のプログラム
for(; i<size; i++){
という書き方もできるのですね。
for文の()内は必ず3つの条件を記入しなければいけないと思っていたので、知りませんでした。
おかげさまですべての問題が解決できました。
ありがとうございます。
という書き方もできるのですね。
for文の()内は必ず3つの条件を記入しなければいけないと思っていたので、知りませんでした。
おかげさまですべての問題が解決できました。
ありがとうございます。