« メモリリークを探る | トップページ | googleのリモートデスクトップが出ましたね »

2014年4月19日 (土)

音が出るまで、のこと その1

音が出るまで、のことを少し書いておきます。

まず、バッファリングの仕組みを入れます。バッファは一般的に利用されるリングバッファを実装します。
といってもそんな大相なものではありませんが…

通信で送られてきたPCMデータをバッファに順次置いてゆきます。同時にタイマーを仕掛けて、定期的にサウンドの再生バッファにデータを書き込みます。書き込んだデータはバッファから取り出されます。実際には取り出されたデータが無効化されるだけですが。

そのようにしてバッファに保持されるPCMデータは、通信スレッドで蓄えられ、タイマー起動された関数によって取り出され消費されます。転送されるデータ量と再生バッファで消費されるデータ量はまちまちなのでバッファ長は伸びたり、縮んだりします。おおよそデータの溢れが起こらないであろうサイズを適当に指定しています。

リングバッファを実現するクラスを適当にでっち上げ(実装し)て、テストしてみました。

テストのため、PCMデータをファイルに順次書き込んでいく仕組みとリングバッファがいっぱいになるまでバッファリングし、いっぱいになったら一気にファイルに書き込む仕組みの2つを入れてテストしました。

リングバッファのサイズを1MBに設定し、バッファが一杯になった時点でファイルへ書き込み、その後プログラムを終了するようにしました。

で、以前書いたsoxコマンドを利用したwavファイルへの変換を行い、2つのPCMファイルを聴き比べました。
ところが、ファイルを順次書き込んでいったファイルは綺麗に聞こえるのですが、バッファリングによって貯めたPCMデータの方のwavファイルは妙に再生時間が短く、再生スピードが早いのです。

バッファリングしたデータは以下です。

「output_buf.wav」をダウンロード

#順次ファイルに書きだしたファイルについてもアップロードしようとしたら1MBの制限に引っかかってしまいました。
#soxコマンドでビットレートの低いMP3に変換できればアップロードできるかも、と思いましたがcygwinで配布しているsoxは当然ながら著作権保護されているMP3はサポートされていません。自分でsoxを作りなおせばいいのですが今回はそこまではしないということで。
#soxの日本語マニュアルはhttp://www.hcn.zaq.ne.jp/___/unix/sox-ja.htmlで公開されています。

soxでトリムしたファイル保存版PCMデータのwavファイルは以下です。

「output_trim.wav」をダウンロード

イメージとしては全く同じPCMデータであるはずなのですが、バイナリエディタで2つのPCM生データファイルを比較すると結構差異が出ています。今回はバイナリエディタStirlingを利用して、比較しました。

Stirling

結構、値としては惜しい感じですが微妙にバイナリ値が異なります…うーん、これは…多分リングバッファへのコピーー時に別スレッドが上書きしている…みたいです。

リングバッファへのアクセス(書き込み、読み込み)は、1度に1スレッドのみに限定する必要があります。でないと別スレッドが上書きしていまい、結果PCMデータが適切に保持できないことになります。

さて、C++でスレッド制御するにはどうするんでしょうか…Javaなら言語仕様的に制御できるようになっているのですが…そこを調べなくてはなりませんでした。

その2へつづく…

« メモリリークを探る | トップページ | googleのリモートデスクトップが出ましたね »

コメント

コメントを書く

コメントは記事投稿者が公開するまで表示されません。

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: 音が出るまで、のこと その1:

« メモリリークを探る | トップページ | googleのリモートデスクトップが出ましたね »