音がでないなぁ その2
Qtでの音の出し方、間違えていました。これだから素人は…
PullだとかPushというのはサンプルソースの実装の仕方による違いでした、すみません。
要は届いたPCMデータをバッファリングしておき、サウンドデバイスに、必要なデータサイズ分のデータをバッファの空きがある限り転送する(write()する)ということのようです。
現状の実装では、届いたデータを届くたびに転送(write)しているので、データが足らず、ブツギリになっているようです。必要なデータが足りていないということのようですね。
サンプルソースではQTimerで20msec毎にイベントを発生させ、呼ばれた関数内でバッファに溜まったデータを転送します。サンプルソースではPCMデータはコンストラクタから呼ばれる関数で生成時にバッファに生成されるため、通信のオーバヘッドを考慮する必要はないので、一定量のPCMデータを用意しておいて、20msecごとに必要な分だけ転送するようになっています。
ですので、ネットワークのオーバヘッドを考慮して、サウンドデバイスへPCMデータを必要な分だけ転送してやることが必要になります。なんとなく先が見えた、ような気がします(^_^;
バッファの空きサイズはQAudioOutputのメンバ関数bytesFree()で調べられます。
デバイスが要求するデータサイズは同じくメンバ関数periodSize()で調べられます。
これを表示するようにしてログを採ってみました。
$ ./debug/qtbrynhildr.exe
Boot : QDateTime("2014-03-27 23:32:09.621 JST Qt::LocalTime")
Assertion SUCCESS : brynhildr.cpp : LINE : 213
[control] Connected for control.
[graphics] Connected for graphics.
[sound] Connected for sound.
[sound] recievedSize = 3840
[sound] recievedSize = 3840
[sound] recievedSize = 5632
[sound] sample rate -> 48000
[sound] stop : IdleState
[sound] start
[sound] bytesFree(): 38400
[sound] periodSize(): 7680
[sound] stop : ActiveState
[sound] recievedSize = 3840
[sound] stop : IdleState
[sound] recievedSize = 3840
[sound] recievedSize = 5888
[sound] sample rate -> 48000
[sound] bytesFree(): 38400
[sound] periodSize(): 7680
[sound] stop : ActiveState
[sound] recievedSize = 7680
[sound] sample rate -> 48000
[sound] bytesFree(): 30720
[sound] periodSize(): 7680
[sound] recievedSize = 1792
[sound] sample rate -> 48000
[sound] bytesFree(): 23040
[sound] periodSize(): 7680
[sound] recievedSize = 5888
[sound] sample rate -> 48000
[sound] bytesFree(): 15360
[sound] periodSize(): 7680
[sound] recievedSize = 3840
[sound] sample rate -> 48000
[sound] bytesFree(): 15360
[sound] periodSize(): 7680
[sound] recievedSize = 5632
サウンドバッファのサイズは38400バイトのようです。この値は、再生中はいろいろ変化します。必要なデータサイズは7680バイトです。これは一定ですね。必要なデータサイズ分ないとbufferunderrunというのが発生します。再生するデータが必要なのにデバイスのバッファにはデータが無いよってことです。現在はこのbufferunderrunが発生しているため、聞き苦しいノイズが発生しています。
適当なサイズ分データを受け取るまで待って、7680バイトの単位で転送すれば良さ気です。ま、これをバッファリングというのですね。リングバッファを実装しなくては…googleさんで調べると…
stackoverflowで質問している人がいますね。
http://stackoverflow.com/questions/19059336/c-threadsafe-ringbuffer-implementation
threadsafeなringbufferらしいです。C++11が実装されたコンパイラでないとだめなそうですが…MinGW-4.8.1なら"-std=c++11"オプションが使えるらしいです、O.K.ですね。しかし、インデックスの計算に割り算を使ってます。バッファサイズを2のべき乗サイズにすれば、ここはAND演算に置き換えられますのでアクセスが速くできそうです。
どうしようかな…
最近のコメント