オーディオファイルからデータを読み書きするための次の2つのシナリオを検討してください(ネットワーク経由で送信するため)。
シナリオ1:オーディオファイルサービス:オーディオファイルサービスのAudioFileReadPacketsを
使用します。これにより、ネットワーク経由で簡単に送信できるオーディオパケットが生成されます。受信側では、 AudioFileStreamOpenとAudioFileStreamParseBytesを使用してデータを解析します。
次に、 AudioFileStreamParseBytesには、 AudioFileStream_PropertyListenerProcとAudioFileStream_PacketsProcの2つのコールバック関数が。これらの人は、ストリームで新しいプロパティが検出されたときと、ストリームからパケットが受信されたときにそれぞれ呼び出されます。パケットを受信したら、ファイルを正常に再生するオーディオキューサービスを使用して、パケットをオーディオキューに送ることができます。
注:この方法は、iPodライブラリに保存されている音楽ファイルでは機能しません。これにより、2番目のシナリオが発生します。
シナリオ2:AVAssetReader:
AVAssetReaderを使用すると、iPodミュージックライブラリから読み取り、ネットワーク経由でパケットを送信できます。通常、上記と同様に、パケットをオーディオキューに直接ロードします。ただし、このシナリオでは、キューがいっぱいになったときにパケットの受信をブロックし、キューバッファーが使用可能になったときにブロックを解除するために、スレッドを作成する必要があります(この例を参照)。
質問:AVAssetReader
を
使用してパケットを送信し、AudioFileStreamParseBytesで読み取ることはできますか?(動機は、AudioFileStreamParseBytesのコールバックがスレッド化/ブロック化ビジネスを処理し、その苦痛を軽減することです)。私はそれを次のようにやってみました:1。最初にAVAssetReaderを使用してオーディオファイルを読み取ります
//NSURL *assetURL = [NSURL URLWithString:@"ipod-library://item/item.m4a?id=1053020204400037178"];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
NSError * error = nil;
AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songAsset error:&error];
AVAssetTrack* track = [songAsset.tracks objectAtIndex:0];
// Note: I don't supply an audio format description here, rather I pass on nil to keep the original
// file format. In another piece of code (see here: http://stackoverflow.com/questions/12264799/why-is-audio-coming-up-garbled-when-using-avassetreader-with-audio-queue?answertab=active#tab-top) I can extract the audio format from the track, let's say it's an AAC format.
AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track
outputSettings:nil];
[reader addOutput:readerOutput];
[reader startReading];
2.ストリーマーを設定します
// notice how i manually add the audio file type (for the file hint parameter)
// using the info from step one.. If i leave it as 0, this call fails and returns
// the typ? error, which is :The specified file type is not supported.
streamer->err = AudioFileStreamOpen((__bridge void*)streamer,
ASPropertyListenerProc, ASPacketsProc,
kAudioFileAAC_ADTSType, &(streamer->audioFileStream));
3.データを受け取ったら、バイトを解析します。
streamer->err = AudioFileStreamParseBytes(streamer->audioFileStream, inDataByteSize, inData, 0);
問題:このようにすると、バイトが送信され、AudioFileStreamParseBytesが失敗しません。ただし、コールバック*AudioFileStream_PropertyListenerProc*および*AudioFileStream_PacketsProc*が呼び出されることはありません。これにより、パーサーはバイトの解析と有用な情報の抽出に失敗したと思います。AudioStreamParseBytesのドキュメントには、次のように記載されています。*少なくとも1パケット以上のオーディオファイルデータを提供する必要がありますが、一度に数秒のデータに数パケットを提供する方が良いです。*GKSessionのデータ制限をわずかに下回る900バイト以上を送信しています。900バイトで十分だと確信しています(シナリオ1でこれをテストすると、毎回合計バイト数は417で、正常に機能しました)。
何か案は?