1

オーディオファイルからデータを読み書きするための次の2つのシナリオを検討してください(ネットワーク経由で送信するため)。

シナリオ1:オーディオファイルサービス:オーディオファイルサービスのAudioFileReadPackets
使用します。これにより、ネットワーク経由で簡単に送信できるオーディオパケットが生成されます。受信側では、 AudioFileStreamOpenAudioFileStreamParseBytesを使用してデータを解析します。

次に、 AudioFileStreamParseBytesには、 AudioFileStream_PropertyListenerProcAudioFileStream_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で、正常に機能しました)。

何か案は?

4

1 に答える 1

3

簡単に言うと、オーディオデータのパケットをAudioFileStreamParseBytesで解析するのは意味がありません。ドキュメントのAudioFileStreamParseBytesは、オーディオファイルの存在に依存する関数です(したがって、AudioFileStreamのパラメータは次のように定義されます。データを渡すパーサーのID。パーサーIDは、AudioFileStreamOpen関数によって返されます。

だから学んだ教訓:あなたの状況に合うようにiOSの機能をピジョンホールにしようとしないでください..それは逆でなければなりません。

私がやったことは、データをオーディオキューに直接フィードすることでした。これらの不要な中間機能をすべて実行することなく、より詳細な方法でデータをオーディオユニットにフィードすることになります。しかし、私のアプリケーションはそのレベルを必要としませんでした。制御の

于 2012-11-22T13:58:28.807 に答える