difference between how AVAssetReader and AudioFileReadPackets reads Audio

consider these two scenarios for reading/writing data from Audio files (for the purpose of sending over a network):

Scenario 1: Audio File Services: Using AudioFileReadPackets from Audio File Services. This generates audio packets that you can easily send over the network. On the receiving side you use AudioFileStreamOpen and AudioFileStreamParseBytes to parse the data.

AudioFileStreamParseBytes then has two callback functions: AudioFileStream_PropertyListenerProc and AudioFileStream_PacketsProc. These guys are called when a new property is discovered in the stream and when packets are received from the stream, respectively. Once you receive the packets, you can feed it to an audio queue using Audio Queue Service which plays the file just fine.

Note: This method does NOT work with music files stored in the iPod library, which brings us to the 2nd scenario:

Scenario 2: AVAssetReader: With AVAssetReader you can read from the iPod music library and send packets over the network. Typically you would load the packets directly on an Audio Queue similar to above. However, in this scenario you will have to create a thread to ensure that you block receiving packets when the queue is full, and unblock when queue buffers are available (see this example).

Question: Is it possible to use AVAssetReader to send packets over, only to have it read by AudioFileStreamParseBytes? (the motive would be that the AudioFileStreamParseBytes's callbacks will handle the threading/blocking business and save you that pain). I tried doing it like so: 1. first read the audio file using 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. set up the streamer

// 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. once I receive the data, I parse the bytes:

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

problem: When I do it this way.. I send the bytes and the AudioFileStreamParseBytes does not fail. However, the callbacks *AudioFileStream_PropertyListenerProc* and *AudioFileStream_PacketsProc* are never called. Which makes me think that the parser has failed to parse the bytes and extract any useful information out of them.. in the documentation for AudioStreamParseBytes it states:* You should provide at least more than a single packet’s worth of audio file data, but it is better to provide a few packets to a few seconds data at a time.* I'm sending over 900 bytes, which is just below GKSession's data limit. I'm pretty sure 900 bytes is enough (when testing this under scenario 1, the total bytes was 417 each time and it worked fine).

Any ideas?

Answers


The short answer is that it simply doesn't make sense to have packets of audio data be parsed by AudioFileStreamParseBytes.. in the docs AudioFileStreamParseBytes is a function dependent on the existence of an audio file (thus the parameter inAudioFileStream.. which is defined as the ID of the parser to which you wish to pass data. The parser ID is returned by the AudioFileStreamOpen function.)

so lesson learned: don't try to pigeon hole iOS functions to fit your situation.. it should be the other way around.

What I ended up doing was feeding the data directly to an Audio Queue.. without going through all these unnecessary intermediary functions.. a more in depth way would be feeding the data to audio units.. but my application didn't need that level of control


Need Your Help

HTML-Popup is always shown with controlbar and the thumbstrip when gallery on Highslide is included

javascript gallery highslide

Highslide is an amazing tool, unfortunately i don't get done with my following projekt. I want to show several galleries with Highslide. Therefore i have included

BindingList and LINQ?

c# .net linq .net-3.5 c#-3.0

I am new with Linq and I would like to sort some data that are in the BindingList. Once I did my Linq query, I need to use back the BindingList collection to bind my data.