From cf9dafc961fe4f3989ac548e61070058279dccc7 Mon Sep 17 00:00:00 2001 From: Syed Haris Ali Date: Sat, 4 Jul 2015 12:54:46 -0700 Subject: [PATCH] updated recording OSX example --- .../Base.lproj/MainMenu.xib | 482 +++++++++++++----- .../RecordViewController.h | 87 +++- .../RecordViewController.m | 298 +++++++---- .../RecordViewController.xib | 149 ++++-- .../MainStoryboard.storyboard | 2 +- .../RecordViewController.h | 4 +- .../RecordViewController.m | 12 - 7 files changed, 705 insertions(+), 329 deletions(-) diff --git a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/Base.lproj/MainMenu.xib b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/Base.lproj/MainMenu.xib index 05ff7446..5e5b49cf 100644 --- a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/Base.lproj/MainMenu.xib +++ b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/Base.lproj/MainMenu.xib @@ -1,100 +1,17 @@ - + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -102,6 +19,9 @@ + + + @@ -116,95 +36,211 @@ - + + + + + + + + + + + + + - - + + + + + - - + + + + + + + + + + - + + + + + - - + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + - + + + + + + + + + + + + + - - - - + + + + + + + + + + - - + + + + + + + + + + + + + @@ -214,18 +250,38 @@ + + + - - + + + + + + + + + + + + + + + + + + + @@ -236,12 +292,21 @@ + + + + + + + + + @@ -249,8 +314,16 @@ - - + + + + + + + + + + @@ -265,13 +338,37 @@ - - - - + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + @@ -279,15 +376,27 @@ + + + + + + + + + + + + @@ -298,12 +407,21 @@ + + + + + + + + + @@ -314,30 +432,55 @@ + + + + + + + + + + + + + + + - + + + + + + + + + + + @@ -346,12 +489,27 @@ - - + + + + + + + + + + + + + + + + + + - @@ -363,14 +521,23 @@ Default + + + Left to Right + + + Right to Left + + + @@ -379,14 +546,23 @@ Default + + + Left to Right + + + Right to Left + + + @@ -394,12 +570,21 @@ + + + + + + + + + @@ -412,20 +597,39 @@ + + + + + + + + - - - + + + + + + + + + + - + + + + + @@ -433,17 +637,21 @@ - + + + + + - + - + @@ -454,14 +662,6 @@ - - - - - - - - - + diff --git a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h index 3fd4fafb..9b32e273 100644 --- a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h +++ b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h @@ -28,51 +28,116 @@ // Import EZAudio header #import "EZAudio.h" -// Import AVFoundation to play the file (will save EZAudioFile and EZOutput for separate example) -#import - // By default this will record a file to /Users/YOUR_USERNAME/Documents/test.caf #define kAudioFilePath [NSString stringWithFormat:@"%@%@",NSHomeDirectory(),@"/Documents/test.m4a"] +//------------------------------------------------------------------------------ +#pragma mark - RecordViewController +//------------------------------------------------------------------------------ + /** We will allow this view controller to act as an EZMicrophoneDelegate. This is how we listen for the microphone callback. */ -@interface RecordViewController : NSViewController +@interface RecordViewController : NSViewController + +/** + The label used to display the current time for recording/playback in the top left + */ +@property (nonatomic, weak) IBOutlet NSTextField *currentTimeLabel; + +//------------------------------------------------------------------------------ /** Use a OpenGL based plot to visualize the data coming in */ -@property (nonatomic,weak) IBOutlet EZAudioPlotGL *audioPlot; +@property (nonatomic, weak) IBOutlet EZAudioPlotGL *recordingAudioPlot; + +//------------------------------------------------------------------------------ /** A flag indicating whether we are recording or not */ -@property (nonatomic,assign) BOOL isRecording; +@property (nonatomic, assign) BOOL isRecording; + +//------------------------------------------------------------------------------ /** The microphone component */ -@property (nonatomic,strong) EZMicrophone *microphone; +@property (nonatomic, strong) EZMicrophone *microphone; + +//------------------------------------------------------------------------------ + +/** + The switch used to toggle the microphone on/off + */ +@property (nonatomic, weak) IBOutlet NSButton *microphoneSwitch; + +//------------------------------------------------------------------------------ + +/** + The audio player that will play the recorded file + */ +@property (nonatomic, strong) EZAudioPlayer *player; + +//------------------------------------------------------------------------------ /** The recorder component */ -@property (nonatomic,strong) EZRecorder *recorder; +@property (nonatomic, strong) EZRecorder *recorder; + +//------------------------------------------------------------------------------ + +/** + The second audio plot used on the top right to display the current playing audio + */ +@property (nonatomic, weak) IBOutlet EZAudioPlot *playingAudioPlot; + +//------------------------------------------------------------------------------ + +/** + The button the user taps to play the recorded audio file + */ +@property (nonatomic, weak) IBOutlet NSButton *playButton; + +//------------------------------------------------------------------------------ + +/** + The label used to display the audio player play state + */ +@property (nonatomic, weak) IBOutlet NSTextField *playingStateLabel; + +//------------------------------------------------------------------------------ +/** + The switch used to toggle the recording on/off + */ +@property (nonatomic, weak) IBOutlet NSButton *recordSwitch; + +//------------------------------------------------------------------------------ #pragma mark - Actions +//------------------------------------------------------------------------------ + /** Stops the recorder and starts playing whatever has been recorded. */ --(IBAction)playFile:(id)sender; +- (IBAction)playFile:(id)sender; + +//------------------------------------------------------------------------------ /** Toggles the microphone on and off. When the microphone is on it will send its delegate (aka this view controller) the audio data in various ways (check out the EZMicrophoneDelegate documentation for more details); */ --(IBAction)toggleMicrophone:(id)sender; +- (IBAction)toggleMicrophone:(id)sender; + +//------------------------------------------------------------------------------ /** Toggles the microphone on and off. When the microphone is on it will send its delegate (aka this view controller) the audio data in various ways (check out the EZMicrophoneDelegate documentation for more details); */ --(IBAction)toggleRecording:(id)sender; +- (IBAction)toggleRecording:(id)sender; @end diff --git a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m index 8e8b0b64..8917654f 100644 --- a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m +++ b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m @@ -25,12 +25,9 @@ #import "RecordViewController.h" -@interface RecordViewController () -@property (nonatomic,strong) AVAudioPlayer *audioPlayer; -@property (nonatomic,weak) IBOutlet NSButton *microphoneToggle; -@property (nonatomic,weak) IBOutlet NSButton *playButton; -@property (nonatomic,weak) IBOutlet NSButton *recordingToggle; -@end +//------------------------------------------------------------------------------ +#pragma mark - RecordViewController (Implementation) +//------------------------------------------------------------------------------ @implementation RecordViewController @@ -38,52 +35,106 @@ @implementation RecordViewController #pragma mark - Customize the Audio Plot //------------------------------------------------------------------------------ --(void)awakeFromNib +- (void)awakeFromNib +{ + + // + // Customizing the audio plot that'll show the current microphone input/recording + // + self.recordingAudioPlot.backgroundColor = [NSColor colorWithRed: 0.984 green: 0.71 blue: 0.365 alpha: 1]; + self.recordingAudioPlot.color = [NSColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]; + self.recordingAudioPlot.plotType = EZPlotTypeRolling; + self.recordingAudioPlot.shouldFill = YES; + self.recordingAudioPlot.shouldMirror = YES; + + // + // Customizing the audio plot that'll show the playback + // + self.playingAudioPlot.color = [NSColor whiteColor]; + self.playingAudioPlot.plotType = EZPlotTypeRolling; + self.playingAudioPlot.shouldFill = YES; + self.playingAudioPlot.shouldMirror = YES; + self.playingAudioPlot.gain = 2.5f; + + // Create an instance of the microphone and tell it to use this view controller instance as the delegate + self.microphone = [EZMicrophone microphoneWithDelegate:self]; + self.player = [EZAudioPlayer audioPlayerWithDelegate:self]; + + // + // Initialize UI components + // + [self setTitle:@"Microphone On" forButton:self.microphoneSwitch]; + [self setTitle:@"Not Recording" forButton:self.recordSwitch]; + self.playingStateLabel.stringValue = @"Not Playing"; + self.playButton.enabled = NO; + + // + // Setup notifications + // + [self setupNotifications]; + + // + // Start the microphone + // + [self.microphone startFetchingAudio]; +} + + +//------------------------------------------------------------------------------ + +- (void)setupNotifications +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(playerDidChangePlayState:) + name:EZAudioPlayerDidChangePlayStateNotification + object:self.player]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(playerDidReachEndOfFile:) + name:EZAudioPlayerDidReachEndOfFileNotification + object:self.player]; +} + +//------------------------------------------------------------------------------ +#pragma mark - Notifications +//------------------------------------------------------------------------------ + +- (void)playerDidChangePlayState:(NSNotification *)notification { - /* - Customizing the audio plot's look - */ - // Background color - self.audioPlot.backgroundColor = [NSColor colorWithCalibratedRed: 0.984 green: 0.71 blue: 0.365 alpha: 1]; - // Waveform color - self.audioPlot.color = [NSColor colorWithCalibratedRed: 1.000 green: 1.000 blue: 1.000 alpha: 1]; - // Plot type - self.audioPlot.plotType = EZPlotTypeRolling; - // Fill - self.audioPlot.shouldFill = YES; - // Mirror - self.audioPlot.shouldMirror = YES; - - // Configure the play button - [self.playButton setHidden:YES]; - - /* - Start the microphone - */ - self.microphone = [EZMicrophone microphoneWithDelegate:self startsImmediately:YES]; - + EZAudioPlayer *player = [notification object]; + BOOL isPlaying = [player isPlaying]; + if (isPlaying) + { + self.recorder.delegate = nil; + } + self.playingStateLabel.stringValue = isPlaying ? @"Playing" : @"Not Playing"; + self.playingAudioPlot.hidden = !isPlaying; +} + +//------------------------------------------------------------------------------ + +- (void)playerDidReachEndOfFile:(NSNotification *)notification +{ + [self.playingAudioPlot clear]; } //------------------------------------------------------------------------------ #pragma mark - Actions //------------------------------------------------------------------------------ --(void)playFile:(id)sender +- (void)playFile:(id)sender { // // Update microphone state // [self.microphone stopFetchingAudio]; - self.microphoneToggle.state = NSOffState; - [self.microphoneToggle setEnabled:NO]; - + // // Update recording state // self.isRecording = NO; - self.recordingToggle.state = NSOffState; - [self.recordingToggle setEnabled:NO]; - + [self setTitle:@"Not Recording" forButton:self.recordSwitch]; + self.recordSwitch.state = NSOffState; + // // Close the audio file // @@ -92,122 +143,157 @@ -(void)playFile:(id)sender [self.recorder closeAudioFile]; } - // - // Create audio player - // - if (self.audioPlayer) - { - if (self.audioPlayer.playing) [self.audioPlayer stop]; - self.audioPlayer = nil; - } - NSError *err; - self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:kAudioFilePath] - error:&err]; - - [self.audioPlayer play]; - self.audioPlayer.delegate = self; + EZAudioFile *audioFile = [EZAudioFile audioFileWithURL:[NSURL fileURLWithPath:kAudioFilePath]]; + [self.player playAudioFile:audioFile]; } //------------------------------------------------------------------------------ --(void)toggleMicrophone:(id)sender +- (void)toggleMicrophone:(id)sender { - switch([sender state]) + [self.player pause]; + + NSInteger state = [(NSButton *)sender state]; + if (state == NSOffState) { - case NSOffState: - [self.microphone stopFetchingAudio]; - break; - case NSOnState: - [self.microphone startFetchingAudio]; - break; - default: - break; + [self.microphone stopFetchingAudio]; + } + else + { + [self.microphone startFetchingAudio]; } } //------------------------------------------------------------------------------ --(void)toggleRecording:(id)sender +- (void)toggleRecording:(id)sender { - [self.playButton setHidden:NO]; - switch( [sender state]) + [self.player pause]; + + NSInteger state = [(NSButton *)sender state]; + if (state == NSOnState) { - case NSOffState: - [self.recorder closeAudioFile]; - break; - case NSOnState: - /* - Create the recorder - */ - self.recorder = [EZRecorder recorderWithDestinationURL:[NSURL fileURLWithPath:kAudioFilePath] - sourceFormat:[self.microphone audioStreamBasicDescription] - destinationFileType:EZRecorderFileTypeM4A]; - break; - default: - break; + // + // Create the recorder + // + [self.microphone startFetchingAudio]; + self.recorder = [EZRecorder recorderWithURL:[NSURL fileURLWithPath:kAudioFilePath] + clientFormat:[self.microphone audioStreamBasicDescription] + fileType:EZRecorderFileTypeM4A + delegate:self]; + self.playButton.enabled = YES; } - self.isRecording = (BOOL)[sender state]; + self.isRecording = state; + NSString *title = self.isRecording ? @"Recording" : @"Not Recording"; + [self setTitle:title forButton:self.recordSwitch]; } //------------------------------------------------------------------------------ #pragma mark - EZMicrophoneDelegate //------------------------------------------------------------------------------ +- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying +{ + self.microphoneSwitch.state = isPlaying; + NSString *title = isPlaying ? @"Microphone On" : @"Microphone Off"; + [self setTitle:title forButton:self.microphoneSwitch]; +} + +//------------------------------------------------------------------------------ + #warning Thread Safety // Note that any callback that provides streamed audio data (like streaming microphone input) happens on a separate audio thread that should not be blocked. When we feed audio data into any of the UI components we need to explicity create a GCD block on the main thread to properly get the UI to work. --(void)microphone:(EZMicrophone *)microphone - hasAudioReceived:(float **)buffer - withBufferSize:(UInt32)bufferSize -withNumberOfChannels:(UInt32)numberOfChannels +- (void) microphone:(EZMicrophone *)microphone + hasAudioReceived:(float **)buffer + withBufferSize:(UInt32)bufferSize + withNumberOfChannels:(UInt32)numberOfChannels { - // Getting audio data as an array of float buffer arrays. What does that mean? Because the audio is coming in as a stereo signal the data is split into a left and right channel. So buffer[0] corresponds to the float* data for the left channel while buffer[1] corresponds to the float* data for the right channel. - - // See the Thread Safety warning above, but in a nutshell these callbacks happen on a separate audio thread. We wrap any UI updating in a GCD block on the main thread to avoid blocking that audio flow. + // Getting audio data as an array of float buffer arrays. What does that mean? Because the audio is coming in as a stereo signal the data is split into a left and right channel. So buffer[0] corresponds to the float* data for the left channel while buffer[1] corresponds to the float* data for the right channel. + + // See the Thread Safety warning above, but in a nutshell these callbacks happen on a separate audio thread. We wrap any UI updating in a GCD block on the main thread to avoid blocking that audio flow. __weak typeof (self) weakSelf = self; - dispatch_async(dispatch_get_main_queue(),^{ - // All the audio plot needs is the buffer data (float*) and the size. Internally the audio plot will handle all the drawing related code, history management, and freeing its own resources. Hence, one badass line of code gets you a pretty plot :) - [weakSelf.audioPlot updateBuffer:buffer[0] - withBufferSize:bufferSize]; + dispatch_async(dispatch_get_main_queue(), ^{ + // All the audio plot needs is the buffer data (float*) and the size. Internally the audio plot will handle all the drawing related code, history management, and freeing its own resources. Hence, one badass line of code gets you a pretty plot :) + [weakSelf.recordingAudioPlot updateBuffer:buffer[0] + withBufferSize:bufferSize]; }); } //------------------------------------------------------------------------------ -// Append the microphone data coming as a AudioBufferList with the specified buffer size to the recorder --(void) microphone:(EZMicrophone *)microphone +- (void) microphone:(EZMicrophone *)microphone hasBufferList:(AudioBufferList *)bufferList withBufferSize:(UInt32)bufferSize withNumberOfChannels:(UInt32)numberOfChannels { - // Getting audio data as a buffer list that can be directly fed into the EZRecorder. This is happening on the audio thread - any UI updating needs a GCD main queue block. + // Getting audio data as a buffer list that can be directly fed into the EZRecorder. This is happening on the audio thread - any UI updating needs a GCD main queue block. This will keep appending data to the tail of the audio file. if (self.isRecording) { [self.recorder appendDataFromBufferList:bufferList withBufferSize:bufferSize]; - } + } } //------------------------------------------------------------------------------ -#pragma mark - AVAudioPlayerDelegate +#pragma mark - EZRecorderDelegate //------------------------------------------------------------------------------ -/* - Occurs when the audio player instance completes playback - */ --(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player - successfully:(BOOL)flag +- (void)recorderDidClose:(EZRecorder *)recorder { - // Update microphone state - self.microphoneToggle.state = NSOnState; - [self.microphoneToggle setEnabled:YES]; - [self.microphone startFetchingAudio]; + recorder.delegate = nil; +} - // Update recording state - self.isRecording = NO; - self.recordingToggle.state = NSOffState; - [self.recordingToggle setEnabled:YES]; +//------------------------------------------------------------------------------ + +- (void)recorderUpdatedCurrentTime:(EZRecorder *)recorder +{ + __weak typeof (self) weakSelf = self; + NSString *formattedCurrentTime = [recorder formattedCurrentTime]; + dispatch_async(dispatch_get_main_queue(), ^{ + weakSelf.currentTimeLabel.stringValue = formattedCurrentTime; + }); +} + +//------------------------------------------------------------------------------ +#pragma mark - EZAudioPlayerDelegate +//------------------------------------------------------------------------------ + +- (void) audioPlayer:(EZAudioPlayer *)audioPlayer + playedAudio:(float **)buffer + withBufferSize:(UInt32)bufferSize + withNumberOfChannels:(UInt32)numberOfChannels + inAudioFile:(EZAudioFile *)audioFile +{ + __weak typeof (self) weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf.playingAudioPlot updateBuffer:buffer[0] + withBufferSize:bufferSize]; + }); } //------------------------------------------------------------------------------ +- (void)audioPlayer:(EZAudioPlayer *)audioPlayer + updatedPosition:(SInt64)framePosition + inAudioFile:(EZAudioFile *)audioFile +{ + __weak typeof (self) weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + weakSelf.currentTimeLabel.stringValue = [audioPlayer formattedCurrentTime]; + }); +} + +//------------------------------------------------------------------------------ +#pragma mark - Utility +//------------------------------------------------------------------------------ + +- (void)setTitle:(NSString *)title forButton:(NSButton *)button +{ + NSDictionary *attributes = @{ NSForegroundColorAttributeName : [NSColor whiteColor] }; + NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title + attributes:attributes]; + button.attributedTitle = attributedTitle; + button.attributedAlternateTitle = attributedTitle; +} + @end diff --git a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.xib b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.xib index c01a6421..4af835f8 100644 --- a/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.xib +++ b/EZAudioExamples/OSX/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.xib @@ -1,79 +1,116 @@ - + - + - - - - + + + + + + + - + - - - - + + + + + + + + + + + - + + + + + + + + + + + + + - - - - - - - - - - + - - - - - - - - - - - + + + + - \ No newline at end of file + diff --git a/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/MainStoryboard.storyboard b/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/MainStoryboard.storyboard index 250e1b9a..4ebd6b68 100644 --- a/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/MainStoryboard.storyboard +++ b/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/MainStoryboard.storyboard @@ -17,7 +17,7 @@ - + diff --git a/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h b/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h index 0c86fa53..9f1d4145 100644 --- a/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h +++ b/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.h @@ -23,7 +23,7 @@ EZRecorderDelegate> /** - <#Description#> + The label used to display the current time for recording/playback in the top left */ @property (nonatomic, weak) IBOutlet UILabel *currentTimeLabel; @@ -32,7 +32,7 @@ /** Use a OpenGL based plot to visualize the data coming in */ -@property (nonatomic, weak) IBOutlet EZAudioPlot *recordingAudioPlot; +@property (nonatomic, weak) IBOutlet EZAudioPlotGL *recordingAudioPlot; //------------------------------------------------------------------------------ diff --git a/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m b/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m index f03daa65..781faff3 100644 --- a/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m +++ b/EZAudioExamples/iOS/EZAudioRecordExample/EZAudioRecordExample/RecordViewController.m @@ -103,10 +103,6 @@ - (void)viewDidLoad - (void)setupNotifications { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(playerDidChangeAudioFile:) - name:EZAudioPlayerDidChangeAudioFileNotification - object:self.player]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerDidChangePlayState:) name:EZAudioPlayerDidChangePlayStateNotification @@ -121,13 +117,6 @@ - (void)setupNotifications #pragma mark - Notifications //------------------------------------------------------------------------------ -- (void)playerDidChangeAudioFile:(NSNotification *)notification -{ - -} - -//------------------------------------------------------------------------------ - - (void)playerDidChangePlayState:(NSNotification *)notification { EZAudioPlayer *player = [notification object]; @@ -174,7 +163,6 @@ - (void)playFile:(id)sender } EZAudioFile *audioFile = [EZAudioFile audioFileWithURL:[self testFilePathURL]]; - NSLog(@"audiofile: %@", audioFile); [self.player playAudioFile:audioFile]; }