Advertisement
Guest User

Augraph

a guest
Jun 12th, 2012
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. //  MZRGraphPlayer.m
  3. //  SimplePlayFileModern
  4. //
  5. //  Created by Michael Hanna on 12-06-11.
  6. //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
  7. //
  8.  
  9. #import "MZRGraphPlayer.h"
  10.  
  11. @interface MZRGraphPlayer()
  12. - (MZRAUGraphPlayer)makePlayerWithFile:(CFURLRef)urlRef_;
  13. - (void)createAUGraph:(MZRAUGraphPlayer *)player_;
  14. - (Float64)prepareFileAU:(MZRAUGraphPlayer *)player_;
  15. @end
  16.  
  17. // generic error handler - if err is nonzero, prints error message and exits program.
  18. static void CheckError(OSStatus error, const char *operation)
  19. {
  20.     if (error == noErr) return;
  21.    
  22.     char str[20];
  23.     // see if it appears to be a 4-char-code
  24.     *(UInt32 *)(str + 1) = CFSwapInt32HostToBig(error);
  25.     if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
  26.         str[0] = str[5] = '\'';
  27.         str[6] = '\0';
  28.     } else
  29.         // no, format it as an integer
  30.         sprintf(str, "%d", (int)error);
  31.    
  32.     fprintf(stderr, "Error: %s (%s)\n", operation, str);
  33.    
  34.     exit(1);
  35. }
  36.  
  37.  
  38. @implementation MZRGraphPlayer
  39. @synthesize _fileURL;
  40. @synthesize _duration;
  41. @synthesize _audioFileRegion;
  42. @synthesize _isPaused;
  43.  
  44. - (void)dealloc
  45. {
  46.   [_fileURL release];
  47.   [super dealloc];
  48. }
  49.  
  50. - (id)init
  51. {
  52.   if ((self = [super init]))
  53.   {
  54.     [self set_fileURL:nil];
  55.     _isPaused = NO;
  56.   }
  57.  
  58.   return self;
  59. }
  60.  
  61. - (void)graphLoadFile:(NSURL *)fileURL_
  62. {
  63.   [self set_fileURL:fileURL_];
  64.   CFURLRef inputFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)[[self _fileURL] path], kCFURLPOSIXPathStyle, false);
  65.   _player = [self makePlayerWithFile:inputFileURL];
  66.   [self createAUGraph:&_player];
  67.  
  68.   // configure the file player
  69.   _duration = [self prepareFileAU:&_player];
  70. }
  71.  
  72. - (void)cleanup
  73. {
  74.   CheckError(AUGraphStop
  75.              (_player.graph), "AUGraphStop failed.");
  76.  
  77.   CheckError(AUGraphUninitialize
  78.              (_player.graph), "AUGraphUninitialize failed.");
  79.  
  80.   CheckError(AUGraphClose
  81.              (_player.graph), "AUGraphClose failed.");
  82.  
  83.   CheckError(AudioFileClose
  84.              (_player.inputFile), "AUGraphStop failed.");
  85. }
  86.  
  87. - (MZRAUGraphPlayer)makePlayerWithFile:(CFURLRef)urlRef_
  88. {
  89.   MZRAUGraphPlayer player = {0};
  90.  
  91.   // open the input audio file
  92.   CheckError(AudioFileOpenURL
  93.              (urlRef_, kAudioFileReadPermission, 0, &player.inputFile), "AudioFileOpenURL failed");
  94.   CFRelease(urlRef_);
  95.  
  96.   // get the audio data format from the file
  97.   UInt32 propSize = sizeof(player.inputFormat);
  98.   CheckError(AudioFileGetProperty
  99.              (player.inputFile, kAudioFilePropertyDataFormat, &propSize, &player.inputFormat), "couldn't get file's data format");
  100.  
  101.   return player;
  102. }
  103.  
  104. - (void)graphStart
  105. {
  106.   if ([self graphIsInitialized] && ![self graphIsRunning])
  107.   {
  108. //    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, kNilOptions), ^ {
  109.       // start playing
  110.       CheckError(AUGraphStart
  111.                  (_player.graph), "AUGraphStart failed");
  112. //    });
  113.   }
  114. }
  115.  
  116. - (BOOL)graphIsInitialized
  117. {
  118.   Boolean initialized;
  119.   CheckError(AUGraphIsInitialized(_player.graph, &initialized), "AUGraphIsInitialized failed");
  120.   return (initialized == 1) ? YES : NO;
  121. }
  122.  
  123. - (BOOL)graphIsRunning
  124. {
  125.   Boolean running;
  126.   CheckError(AUGraphIsRunning(_player.graph, &running), "AUGraphIsRunning failed");
  127.   return (running == 1) ? YES : NO;
  128. }
  129.  
  130. - (void)graphStop
  131. {
  132.   if ([self graphIsRunning])
  133.   {
  134.     CheckError(AUGraphStop(_player.graph), "AUGraphStop failed");
  135.   }
  136. }
  137.  
  138. - (void)createAUGraph:(MZRAUGraphPlayer *)player_
  139. {
  140.     // create a new AUGraph
  141.     CheckError(NewAUGraph
  142.              (&player_->graph), "NewAUGraph failed");
  143.    
  144.     // generate description that will match out output device (speakers)
  145.     AudioComponentDescription outputcd = {0};
  146.     outputcd.componentType = kAudioUnitType_Output;
  147.     outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
  148.     outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
  149.    
  150.     // adds a node with above description to the graph
  151.     AUNode outputNode;
  152.     CheckError(AUGraphAddNode
  153.              (player_->graph, &outputcd, &outputNode),"AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed");
  154.    
  155.     // generate description that will match a generator AU of type: audio file player
  156.     AudioComponentDescription fileplayercd = {0};
  157.     fileplayercd.componentType = kAudioUnitType_Generator;
  158.     fileplayercd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
  159.     fileplayercd.componentManufacturer = kAudioUnitManufacturer_Apple;
  160.    
  161.     // adds a node with above description to the graph
  162.     AUNode fileNode;
  163.     CheckError(AUGraphAddNode
  164.              (player_->graph, &fileplayercd, &fileNode), "AUGraphAddNode[kAudioUnitSubType_AudioFilePlayer] failed");
  165.    
  166.     // opening the graph opens all contained audio units but does not allocate any resources yet
  167.     CheckError(AUGraphOpen
  168.              (player_->graph), "AUGraphOpen failed");
  169.    
  170.     // get the reference to the AudioUnit object for the file player graph node
  171.     CheckError(AUGraphNodeInfo
  172.              (player_->graph, fileNode, NULL, &player_->fileAU), "AUGraphNodeInfo failed");
  173.    
  174.     // connect the output source of the file player AU to the input source of the output node
  175.     CheckError(AUGraphConnectNodeInput
  176.              (player_->graph, fileNode, 0, outputNode, 0), "AUGraphConnectNodeInput");
  177.    
  178.     // now initialize the graph (causes resources to be allocated)
  179.     CheckError(AUGraphInitialize
  180.              (player_->graph), "AUGraphInitialize failed");
  181.  
  182. }
  183.  
  184. - (Float64)prepareFileAU:(MZRAUGraphPlayer *)player_
  185. {
  186.     // tell the file player unit to load the file we want to play
  187.     CheckError(AudioUnitSetProperty
  188.              (player_->fileAU, kAudioUnitProperty_ScheduledFileIDs, kAudioUnitScope_Global, 0, &player_->inputFile, sizeof(player_->inputFile)),
  189.              "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFileIDs] failed");
  190.    
  191.     UInt64 nPackets;
  192.     UInt32 propsize = sizeof(nPackets);
  193.     CheckError(AudioFileGetProperty
  194.              (player_->inputFile, kAudioFilePropertyAudioDataPacketCount, &propsize, &nPackets),
  195.              "AudioFileGetProperty[kAudioFilePropertyAudioDataPacketCount] failed");
  196.    
  197.     // tell the file player AU to play the entire file
  198.     ScheduledAudioFileRegion rgn;
  199.     memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp));
  200.     rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
  201.     rgn.mTimeStamp.mSampleTime = 0;
  202.     rgn.mCompletionProc = NULL;
  203.     rgn.mCompletionProcUserData = NULL;
  204.     rgn.mAudioFile = player_->inputFile;
  205.     rgn.mLoopCount = 1;
  206.     rgn.mStartFrame = 0;
  207.     rgn.mFramesToPlay = nPackets * player_->inputFormat.mFramesPerPacket;
  208.    
  209.   [self set_audioFileRegion:rgn];
  210.  
  211.     CheckError(AudioUnitSetProperty
  212.              (player_->fileAU, kAudioUnitProperty_ScheduledFileRegion, kAudioUnitScope_Global, 0,&rgn, sizeof(rgn)),
  213.              "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFileRegion] failed");
  214.    
  215.     // prime the file player AU with default values
  216.     UInt32 defaultVal = 0;
  217.     CheckError(AudioUnitSetProperty
  218.              (player_->fileAU, kAudioUnitProperty_ScheduledFilePrime, kAudioUnitScope_Global, 0, &defaultVal, sizeof(defaultVal)),
  219.              "AudioUnitSetProperty[kAudioUnitProperty_ScheduledFilePrime] failed");
  220.    
  221.     // tell the file player AU when to start playing (-1 sample time means next render cycle)
  222.     AudioTimeStamp startTime;
  223.     memset (&startTime, 0, sizeof(startTime));
  224.     startTime.mFlags = kAudioTimeStampSampleTimeValid;
  225.     startTime.mSampleTime = -1;
  226.     CheckError(AudioUnitSetProperty
  227.              (player_->fileAU, kAudioUnitProperty_ScheduleStartTimeStamp, kAudioUnitScope_Global, 0, &startTime, sizeof(startTime)),
  228.              "AudioUnitSetProperty[kAudioUnitProperty_ScheduleStartTimeStamp]");
  229.    
  230.   AURenderCallbackStruct input;
  231.     input.inputProc = FileRenderProc;
  232.     input.inputProcRefCon = player_;
  233.     CheckError(AudioUnitSetProperty
  234.              (player_->fileAU, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)), "AudioUnitSetProperty failed");
  235.  
  236.     // file duration
  237.     return (nPackets * player_->inputFormat.mFramesPerPacket) / player_->inputFormat.mSampleRate;
  238. }
  239.  
  240. OSStatus FileRenderProc(void *inRefCon,
  241.                             AudioUnitRenderActionFlags *ioActionFlags,
  242.                             const AudioTimeStamp *inTimeStamp,
  243.                             UInt32 inBusNumber,
  244.                             UInt32 inNumberFrames,
  245.                             AudioBufferList * ioData);
  246.  
  247. #pragma mark - callback function -
  248. OSStatus FileRenderProc(void *inRefCon,
  249.                             AudioUnitRenderActionFlags *ioActionFlags,
  250.                             const AudioTimeStamp *inTimeStamp,
  251.                             UInt32 inBusNumber,
  252.                             UInt32 inNumberFrames,
  253.                             AudioBufferList * ioData)
  254. {
  255.   printf ("FileRenderProc needs %u frames at %f\n", inNumberFrames, CFAbsoluteTimeGetCurrent());
  256.    
  257.     MZRAUGraphPlayer *player = (MZRAUGraphPlayer*)inRefCon;
  258.     printf("player %d", player);
  259.     return noErr;
  260. }  
  261.  
  262.  
  263. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement