iOS 4.1: using AVAssetReader to stream from an audio file interrupts audio callback
iOS 4.1: using AVAssetReader to stream from an audio file interrupts audio callback
- Subject: iOS 4.1: using AVAssetReader to stream from an audio file interrupts audio callback
- From: Nikolai Collinsky <email@hidden>
- Date: Sun, 24 Oct 2010 11:51:25 +0100
Dear all,
I've scratched my head over this for many days, and would now like to request help. I wanted to get floating point samples from any track in the iPod Library, which should be straight forward with new AVAssetReader facilities in iOS 4.1 (I'm working with Xcode 3.2.4, 4.1 SDK, with an iPod Touch at 4.1). There is very little info I could find online, and no real examples in the documentation. The setting is live fx processing on floating point audio obtained in a stream from an arbitrary audio file in the ipod library (I've done this previously, i.e., for the BBCut iphone app, with the help of iPod Library Access http://blog.tapsquare.com/post/803301658/ipod-library-access under iOS 4.0). I enclose an excerpt of my code below (I've hidden the producer-consumer thread details; this all runs on a background thread) which has the following problems:
If I use
AVAssetReaderTrackOutput * readaudiofile = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:audioSetting];
The program freezes on that line!
outputSettings: nil would work, but then I don't get any sensible sample values back.
So I use AVAssetReaderAudioMixOutput (see below) but then my interruption callback for the audio session gets called directly after
BOOL lastcheck = [filereader startReading];
And the audio callback stops being called.
I'm imagining some manifestation of hardware vs software decoder, wrong audio session properties and the like. I'm currently using kAudioSessionCategory_MediaPlayback
but have also tried alternatives, without any success. Any obvious gotchas in the below or thoughts on making this work?
best,
Nick
//simplified; audio callback already in progress before running the below. outURL is obtained from selecting something previously from the media library
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
AVURLAsset * asset = [AVURLAsset URLAssetWithURL:outURL options:options];
NSError *error = nil;
AVAssetReader * filereader= [AVAssetReader assetReaderWithAsset:(AVAsset *)asset error:&error];
if (error==nil) {
//get sound file tracks
NSArray * tracks = asset.tracks;
NSUInteger numtracks = tracks.count;
AVAssetTrack * track = [tracks objectAtIndex:0];
//http://objective-audio.jp/2010/09/avassetreaderavassetwriter.html
NSDictionary *audioSetting = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:44100.0],AVSampleRateKey,
[NSNumber numberWithInt:2],AVNumberOfChannelsKey,
[NSNumber numberWithInt:32],AVLinearPCMBitDepthKey, //was 16
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithBool:YES], AVLinearPCMIsFloatKey, //was NO
[NSNumber numberWithBool:0], AVLinearPCMIsBigEndianKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSData data], AVChannelLayoutKey, nil];
//if mono will convert it to stereo?
//should only be one track anyway
AVAssetReaderAudioMixOutput * readaudiofile = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:(asset.tracks) audioSettings:audioSetting];
//claim in source file that AVAssetReaderTrackOutput should be used!
//but this line freezes program
//AVAssetReaderTrackOutput * readaudiofile = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:audioSetting];
[readaudiofile retain];
BOOL yesorno = [filereader canAddOutput:(AVAssetReaderOutput *)readaudiofile];
if (yesorno==NO) goto audiofileProblem;
[filereader addOutput:(AVAssetReaderOutput *)readaudiofile];
//NSString *mediaType = [readaudiofile mediaType]; //soun
//this line will force callbackInterruptionListener to be called!!!!!!!!!!!!
BOOL lastcheck = [filereader startReading];
if (lastcheck==NO) goto audiofileProblem;
//next code is called within a loop over and over, populating a buffer with an eye on read and write pointer positions
CMSampleBufferRef ref = [readaudiofile copyNextSampleBuffer];
Boolean nexttest = CMSampleBufferDataIsReady(ref);
//finished?
if (nexttest==NO)
goto audiofileProblem;
CMItemCount countsamp= CMSampleBufferGetNumSamples(ref);
UInt32 frameCount = countsamp;
CMBlockBufferRef blockBuffer;
AudioBufferList audioBufferList;
//allocates new buffer memory
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList),NULL, NULL, 0, &blockBuffer);
float * buffer = (float * ) audioBufferList.mBuffers[0].mData;
//NOW store samples for use by audio callback
CFRelease(ref);
CFRelease(blockBuffer);
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden