2013年1月29日火曜日

(iOS) UISlider::setValueでsliderが再描画されない。

UISlider::setValueはUIスレッドから呼び出さないと再描画処理が行われません。
別スレッドから読んでいる場合はUIスレッドから呼ぶようにしましょう。

[self performSelectorOnMainThread:@selector(updateSlider) withObject:nil waitUntilDone:NO];

ExtAudioFileSeek→ExtAudioFileReadでError -50

iOSで音楽の読み込みを行うAPIにExtAudioFileRead( fileReference , size,  buffer )がある。

また、シークするAPIとしてExtAudioFileSeek( fileReference, seekTo )がある。

ExtAudioFileSeekを呼び出すことで読み出し位置を変更できるのだが、ファイルを最後まで読みだした後にExtAudioFileSeekで適当な位置にシークし、再びExtAudioFileReadで読みだしても、error -50が返され読み出しに失敗する。(読み出しバイト数は0となっている。)

全然原因がわからなくて調べていたら全く同じ内容で困ってる人がいた

なんと、バッファのサイズを示すbuffer->mBuffers[i].mDataByteSizeが、ExtAudioFileReadで読み出されたデータのバイト数で上書きされてしまうとのこと。

なので、ファイル終端まで再生すると、ファイル終端では読み出されるデータのバイト数が0になるため、buffer->mBuffers[i].mDataByteSizeも0になってしまう。

で、その後シークして読み出そうとしても、サイズ0のバッファをExtAudioFileReadに渡した事になり、データの読みだしが1byteも行われないのである。

というわけで、解決策はExtAudioFileReadを実行したら必ずbuffer->mBuffers[i].mDataByteSizeを実際に確保しているバッファサイズで上書きすること。

ExtAudioFileRead(fileReference, &size, buffer);
for(UInt32 i=0 ; isourceBuffer->mNumberBuffers ; i++){
   buffer->mBuffers[i].mDataByteSize = BUFF_SIZE;
}

ExtAudioFileReadの2つ目の引数sizeが、読みだすサイズの指定をしながら、実際に読み出されたbyte数で上書きされる、っていう仕様はまぁよくある話だけど、さらに他の引数で与えた構造体のメンバも同じデータで上書きするってのはちょっと仕様としてどうなの?これはExtAudioFileReadのリファレンスに何か書いてくれなきゃわかんないよう。