AVAssetReader和AudioFileReadPackets如何读取audio之间的区别

考虑从audio文件读取/写入数据的这两种情况(用于通过networking发送):

场景1:audio文件服务:
从audio文件服务使用AudioFileReadPackets 。 这会生成您可以通过networking轻松发送的audio数据包。 在接收端使用AudioFileStreamOpenAudioFileStreamParseBytes来parsing数据。

AudioFileStreamParseBytes然后有两个callback函数: AudioFileStream_PropertyListenerProc和AudioFileStream_PacketsProc 。 当在stream中发现一个新的属性,并分别从stream接收到数据包时,这些家伙被调用。 一旦你收到数据包,你可以使用audio队列服务将它提供给audio队列,播放文件就好了。

注意:此方法不适用于存储在iPod库中的音乐文件,这会将我们带到第二个场景:

场景2:AVAssetReader:
借助AVAssetReader,您可以从iPod音乐库中读取数据并通过networking发送数据包。 通常情况下,您将直接在类似于上面的audio队列中加载数据包。 但是,在这种情况下,您将不得不创build一个线程,以确保在队列已满时阻止接收数据包,并在队列缓冲区可用时解除阻塞(请参阅此示例)。

题:
是否有可能使用AVAssetReader发送数据包,只有通过AudioFileStreamParseBytes读取? (动机是AudioFileStreamParseBytes的callback将处理线程/阻塞业务,并节省您的痛苦)。 我试图这样做:
1.首先使用AVAssetReader读取audio文件

//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.设置stream光

 // 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.一旦我收到数据,我parsing字节:

 streamer->err = AudioFileStreamParseBytes(streamer->audioFileStream, inDataByteSize, inData, 0); 

问题:当我这样做..我发送的字节和AudioFileStreamParseBytes不会失败。 但是,callback* AudioFileStream_PropertyListenerProc *和* AudioFileStream_PacketsProc *永远不会被调用。 这使我认为parsing器无法parsing字节并从中提取任何有用的信息。在AudioStreamParseBytes的文档中,它指出:*您应该提供至less多个单个数据包的audio文件数据,但它最好是一次提供几个数据包到几秒钟的数据。*我发送超过900个字节,这低于GKSession的数据限制 。 我非常确定900字节就足够了(在场景1下testing时,总的字节数是417,而且工作正常)。

有任何想法吗?

简单的答案是,AudioFileStreamParseBytes在文档中parsingaudio数据包根本没有意义。AudioFileStreamParseBytes是一个依赖于audio文件存在的函数(因此参数inAudioFileStream ..定义为您希望传递数据的parsing器的ID,parsing器ID由AudioFileStreamOpen函数返回。

所以吸取教训:不要尝试鸽子洞iOSfunction,以适应你的情况..应该是相反的方式。

我最终做的是直接将数据馈送到audio队列..而不经历所有这些不必要的中介function..更深入的方式是将数据馈送到audio单元..但是我的应用程序不需要那个级别的控制