Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // MZRGraphPlayer.m
- // SimplePlayFileModern
- //
- // Created by Michael Hanna on 12-06-11.
- // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
- //
- #import "MZRGraphPlayer.h"
- @interface MZRGraphPlayer()
- - (MZRAUGraphPlayer)makePlayerWithFile:(CFURLRef)urlRef_;
- - (void)createAUGraph:(MZRAUGraphPlayer *)player_;
- - (Float64)prepareFileAU:(MZRAUGraphPlayer *)player_;
- @end
- // generic error handler - if err is nonzero, prints error message and exits program.
- static void CheckError(OSStatus error, const char *operation)
- {
- if (error == noErr) return;
- char str[20];
- // see if it appears to be a 4-char-code
- *(UInt32 *)(str + 1) = CFSwapInt32HostToBig(error);
- if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
- str[0] = str[5] = '\'';
- str[6] = '\0';
- } else
- // no, format it as an integer
- sprintf(str, "%d", (int)error);
- fprintf(stderr, "Error: %s (%s)\n", operation, str);
- exit(1);
- }
- @implementation MZRGraphPlayer
- @synthesize _fileURL;
- @synthesize _duration;
- @synthesize _audioFileRegion;
- @synthesize _isPaused;
- - (void)dealloc
- {
- [_fileURL release];
- [super dealloc];
- }
- - (id)init
- {
- if ((self = [super init]))
- {
- [self set_fileURL:nil];
- _isPaused = NO;
- }
- return self;
- }
- - (void)graphLoadFile:(NSURL *)fileURL_
- {
- [self set_fileURL:fileURL_];
- CFURLRef inputFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)[[self _fileURL] path], kCFURLPOSIXPathStyle, false);
- _player = [self makePlayerWithFile:inputFileURL];
- [self createAUGraph:&_player];
- // configure the file player
- _duration = [self prepareFileAU:&_player];
- }
- - (void)cleanup
- {
- CheckError(AUGraphStop
- (_player.graph), "AUGraphStop failed.");
- CheckError(AUGraphUninitialize
- (_player.graph), "AUGraphUninitialize failed.");
- CheckError(AUGraphClose
- (_player.graph), "AUGraphClose failed.");
- CheckError(AudioFileClose
- (_player.inputFile), "AUGraphStop failed.");
- }
- - (MZRAUGraphPlayer)makePlayerWithFile:(CFURLRef)urlRef_
- {
- MZRAUGraphPlayer player = {0};
- // open the input audio file
- CheckError(AudioFileOpenURL
- (urlRef_, kAudioFileReadPermission, 0, &player.inputFile), "AudioFileOpenURL failed");
- CFRelease(urlRef_);
- // get the audio data format from the file
- UInt32 propSize = sizeof(player.inputFormat);
- CheckError(AudioFileGetProperty
- (player.inputFile, kAudioFilePropertyDataFormat, &propSize, &player.inputFormat), "couldn't get file's data format");
- return player;
- }
- - (void)graphStart
- {
- if ([self graphIsInitialized] && ![self graphIsRunning])
- {
- // dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, kNilOptions), ^ {
- // start playing
- CheckError(AUGraphStart
- (_player.graph), "AUGraphStart failed");
- // });
- }
- }
- - (BOOL)graphIsInitialized
- {
- Boolean initialized;
- CheckError(AUGraphIsInitialized(_player.graph, &initialized), "AUGraphIsInitialized failed");
- return (initialized == 1) ? YES : NO;
- }
- - (BOOL)graphIsRunning
- {
- Boolean running;
- CheckError(AUGraphIsRunning(_player.graph, &running), "AUGraphIsRunning failed");
- return (running == 1) ? YES : NO;
- }
- - (void)graphStop
- {
- if ([self graphIsRunning])
- {
- CheckError(AUGraphStop(_player.graph), "AUGraphStop failed");
- }
- }
- - (void)createAUGraph:(MZRAUGraphPlayer *)player_
- {
- // create a new AUGraph
- CheckError(NewAUGraph
- (&player_->graph), "NewAUGraph failed");
- // generate description that will match out output device (speakers)
- AudioComponentDescription outputcd = {0};
- outputcd.componentType = kAudioUnitType_Output;
- outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
- outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
- // adds a node with above description to the graph
- AUNode outputNode;
- CheckError(AUGraphAddNode
- (player_->graph, &outputcd, &outputNode),"AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed");
- // generate description that will match a generator AU of type: audio file player
- AudioComponentDescription fileplayercd = {0};
- fileplayercd.componentType = kAudioUnitType_Generator;
- fileplayercd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
- fileplayercd.componentManufacturer = kAudioUnitManufacturer_Apple;
- // adds a node with above description to the graph
- AUNode fileNode;
- CheckError(AUGraphAddNode
- (player_->graph, &fileplayercd, &fileNode), "AUGraphAddNode[kAudioUnitSubType_AudioFilePlayer] failed");
- // opening the graph opens all contained audio units but does not allocate any resources yet
- CheckError(AUGraphOpen
- (player_->graph), "AUGraphOpen failed");
- // get the reference to the AudioUnit object for the file player graph node
- CheckError(AUGraphNodeInfo
- (player_->graph, fileNode, NULL, &player_->fileAU), "AUGraphNodeInfo failed");
- // connect the output source of the file player AU to the input source of the output node
- CheckError(AUGraphConnectNodeInput
- (player_->graph, fileNode, 0, outputNode, 0), "AUGraphConnectNodeInput");
- // now initialize the graph (causes resources to be allocated)
- CheckError(AUGraphInitialize
- (player_->graph), "AUGraphInitialize failed");
- }
- - (Float64)prepareFileAU:(MZRAUGraphPlayer *)player_
- {
- // tell the file player unit to load the file we want to play
- CheckError(AudioUnitSetProperty
- (player_->fileAU, kAudioUnitProperty_ScheduledFileIDs, kAudioUnitScope_Global, 0, &player_->inputFile, sizeof(player_->inputFile)),
- "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFileIDs] failed");
- UInt64 nPackets;
- UInt32 propsize = sizeof(nPackets);
- CheckError(AudioFileGetProperty
- (player_->inputFile, kAudioFilePropertyAudioDataPacketCount, &propsize, &nPackets),
- "AudioFileGetProperty[kAudioFilePropertyAudioDataPacketCount] failed");
- // tell the file player AU to play the entire file
- ScheduledAudioFileRegion rgn;
- memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp));
- rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
- rgn.mTimeStamp.mSampleTime = 0;
- rgn.mCompletionProc = NULL;
- rgn.mCompletionProcUserData = NULL;
- rgn.mAudioFile = player_->inputFile;
- rgn.mLoopCount = 1;
- rgn.mStartFrame = 0;
- rgn.mFramesToPlay = nPackets * player_->inputFormat.mFramesPerPacket;
- [self set_audioFileRegion:rgn];
- CheckError(AudioUnitSetProperty
- (player_->fileAU, kAudioUnitProperty_ScheduledFileRegion, kAudioUnitScope_Global, 0,&rgn, sizeof(rgn)),
- "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFileRegion] failed");
- // prime the file player AU with default values
- UInt32 defaultVal = 0;
- CheckError(AudioUnitSetProperty
- (player_->fileAU, kAudioUnitProperty_ScheduledFilePrime, kAudioUnitScope_Global, 0, &defaultVal, sizeof(defaultVal)),
- "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFilePrime] failed");
- // tell the file player AU when to start playing (-1 sample time means next render cycle)
- AudioTimeStamp startTime;
- memset (&startTime, 0, sizeof(startTime));
- startTime.mFlags = kAudioTimeStampSampleTimeValid;
- startTime.mSampleTime = -1;
- CheckError(AudioUnitSetProperty
- (player_->fileAU, kAudioUnitProperty_ScheduleStartTimeStamp, kAudioUnitScope_Global, 0, &startTime, sizeof(startTime)),
- "AudioUnitSetProperty[kAudioUnitProperty_ScheduleStartTimeStamp]");
- AURenderCallbackStruct input;
- input.inputProc = FileRenderProc;
- input.inputProcRefCon = player_;
- CheckError(AudioUnitSetProperty
- (player_->fileAU, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)), "AudioUnitSetProperty failed");
- // file duration
- return (nPackets * player_->inputFormat.mFramesPerPacket) / player_->inputFormat.mSampleRate;
- }
- OSStatus FileRenderProc(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList * ioData);
- #pragma mark - callback function -
- OSStatus FileRenderProc(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList * ioData)
- {
- printf ("FileRenderProc needs %u frames at %f\n", inNumberFrames, CFAbsoluteTimeGetCurrent());
- MZRAUGraphPlayer *player = (MZRAUGraphPlayer*)inRefCon;
- printf("player %d", player);
- return noErr;
- }
- @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement