考虑从音频文件读取/写入数据的这两种情况(为了通过网络发送):
场景 1:音频文件服务:
使用音频文件服务中的AudioFileReadPackets。这会生成您可以轻松通过网络发送的音频数据包。在接收端,您使用 AudioFileStreamOpen和AudioFileStreamParseBytes来解析数据。
AudioFileStreamParseBytes然后有两个回调函数: AudioFileStream_PropertyListenerProc和AudioFileStream_PacketsProc。当在流中发现新属性和从流中接收到数据包时,分别调用这些家伙。收到数据包后,您可以使用音频队列服务将其提供给音频队列,该服务可以正常播放文件。
注意:此方法不适用于存储在 iPod 库中的音乐文件,这将我们带到了第二种情况:
场景 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的文档中它指出:* 您应该提供至少超过一个数据包的音频文件数据,但它最好一次提供几个数据包到几秒钟的数据。*我正在发送超过 900 个字节,这刚好低于 GKSession 的数据限制。我很确定 900 字节就足够了(在场景 1 下测试时,每次总字节数为 417 并且工作正常)。
有任何想法吗?