« 配布方法を考える | トップページ | 音がでないなぁ その3 »

2014年3月27日 (木)

音がでないなぁ その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演算に置き換えられますのでアクセスが速くできそうです。

どうしようかな…

« 配布方法を考える | トップページ | 音がでないなぁ その3 »

コメント

コメントを書く

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

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

トラックバック


この記事へのトラックバック一覧です: 音がでないなぁ その2:

« 配布方法を考える | トップページ | 音がでないなぁ その3 »