rewrote EZAudioPlayer to use new EZOutput, added notifications, added NSCopying protocol to EZAudioFile, updated play file examples for iOS and Mac
This commit is contained in:
+2
-2
@@ -149,8 +149,8 @@
|
||||
<connections>
|
||||
<outlet property="audioPlot" destination="kt3-hw-eFY" id="9mm-d1-vJk"/>
|
||||
<outlet property="filePathLabel" destination="i5r-ex-ukW" id="GRl-ld-nWi"/>
|
||||
<outlet property="framePositionSlider" destination="Oc2-kU-kAJ" id="z0M-Q9-JAb"/>
|
||||
<outlet property="rollingHistorySlider" destination="2qJ-Va-Qht" id="yf8-JW-5yM"/>
|
||||
<outlet property="positionSlider" destination="Oc2-kU-kAJ" id="ZBM-XQ-gzp"/>
|
||||
<outlet property="rollingHistorySlider" destination="2qJ-Va-Qht" id="8rE-j3-utb"/>
|
||||
<outlet property="view" destination="PED-9r-Xub" id="Xxb-En-D2X"/>
|
||||
<outlet property="volumeSlider" destination="d3R-ct-df2" id="pAW-BF-AFa"/>
|
||||
</connections>
|
||||
|
||||
+43
-18
@@ -16,79 +16,104 @@
|
||||
*/
|
||||
#define kAudioFileDefault [[NSBundle mainBundle] pathForResource:@"simple-drum-beat" ofType:@"wav"]
|
||||
|
||||
/**
|
||||
Using the EZOutputDataSource to provide output data to the EZOutput component.
|
||||
*/
|
||||
@interface PlayFileViewController : UIViewController <EZAudioFileDelegate,
|
||||
EZOutputDataSource,
|
||||
EZOutputDelegate>
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma mark - PlayFileViewController
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#pragma mark - Components
|
||||
/**
|
||||
The EZAudioFile representing of the currently selected audio file
|
||||
The PlayFileViewController will demonstrate how to play an audio file and plot
|
||||
the audio data in real-time.
|
||||
*/
|
||||
@interface PlayFileViewController : UIViewController <EZAudioPlayerDelegate>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma mark - Components
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
An EZAudioFile that will be used to load the audio file at the file path specified
|
||||
*/
|
||||
@property (nonatomic, strong) EZAudioFile *audioFile;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
The EZOutput representing the output currently being used to play the audio file.
|
||||
An EZAudioPlayer that will be used for playback
|
||||
*/
|
||||
@property (nonatomic, strong) EZOutput *output;
|
||||
@property (nonatomic, strong) EZAudioPlayer *player;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
The CoreGraphics based audio plot
|
||||
*/
|
||||
@property (nonatomic, weak) IBOutlet EZAudioPlot *audioPlot;
|
||||
|
||||
#pragma mark - UI Extras
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
A label to display the current file path with the waveform shown
|
||||
*/
|
||||
@property (nonatomic, weak) IBOutlet UILabel *filePathLabel;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
A slider to indicate the current frame position in the audio file
|
||||
*/
|
||||
@property (nonatomic, weak) IBOutlet UISlider *framePositionSlider;
|
||||
@property (nonatomic, weak) IBOutlet UISlider *positionSlider;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
A slider to indicate the current rolling history length of the audio plot.
|
||||
A slider to indicate the rolling history length of the audio plot.
|
||||
*/
|
||||
@property (nonatomic, weak) IBOutlet UISlider *rollingHistorySlider;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
A slider to indicate the volume on the audio player
|
||||
*/
|
||||
@property (nonatomic, weak) IBOutlet UISlider *volumeSlider;
|
||||
|
||||
/**
|
||||
A BOOL indicating whether or not we've reached the end of the file
|
||||
*/
|
||||
@property (nonatomic,assign) BOOL eof;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma mark - Actions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Switches the plot drawing type between a buffer plot (visualizes the current stream of audio data from the update function) or a rolling plot (visualizes the audio data over time, this is the classic waveform look)
|
||||
*/
|
||||
- (IBAction)changePlotType:(id)sender;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Changes the length of the rolling history of the audio plot.
|
||||
*/
|
||||
- (IBAction)changeRollingHistoryLength:(id)sender;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Changes the volume of the audio player.
|
||||
*/
|
||||
- (IBAction)changeVolume:(id)sender;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Begins playback if a file is loaded. Pauses if the file is already playing.
|
||||
*/
|
||||
- (IBAction)play:(id)sender;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Seeks to a specific frame in the audio file.
|
||||
*/
|
||||
- (IBAction)seekToFrame:(id)sender;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@end
|
||||
|
||||
+68
-122
@@ -20,53 +20,31 @@
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
//
|
||||
// Setup the AVAudioSession. EZMicrophone will not work properly on iOS
|
||||
// if you don't do this!
|
||||
//
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
NSError *error;
|
||||
[session setCategory:AVAudioSessionCategoryPlayback error:&error];
|
||||
if (error)
|
||||
{
|
||||
NSLog(@"Error setting up audio session category: %@", error.localizedDescription);
|
||||
}
|
||||
[session setActive:YES error:&error];
|
||||
if (error)
|
||||
{
|
||||
NSLog(@"Error setting up audio session active: %@", error.localizedDescription);
|
||||
}
|
||||
|
||||
//
|
||||
// Customize the plot's look
|
||||
// Customizing the audio plot's look
|
||||
//
|
||||
// Background color
|
||||
self.audioPlot.backgroundColor = [UIColor colorWithRed: 0.816 green: 0.349 blue: 0.255 alpha: 1];
|
||||
// Waveform color
|
||||
self.audioPlot.color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
|
||||
// Plot type
|
||||
self.audioPlot.plotType = EZPlotTypeBuffer;
|
||||
// Fill
|
||||
self.audioPlot.shouldFill = YES;
|
||||
// Mirror
|
||||
self.audioPlot.shouldMirror = YES;
|
||||
|
||||
//
|
||||
// Create an EZOutput instance
|
||||
//
|
||||
self.output = [EZOutput outputWithDataSource:self];
|
||||
self.output.delegate = self;
|
||||
|
||||
//
|
||||
// Customize UI controls
|
||||
// Create the audio player
|
||||
//
|
||||
self.volumeSlider.value = [self.output volume];
|
||||
self.rollingHistorySlider.value = [self.audioPlot rollingHistoryLength];
|
||||
self.player = [EZAudioPlayer audioPlayer];
|
||||
self.player.delegate = self;
|
||||
self.player.shouldLoop = YES;
|
||||
|
||||
//
|
||||
// Try opening the sample file
|
||||
// Customize UI components
|
||||
//
|
||||
self.rollingHistorySlider.value = (float)[self.audioPlot rollingHistoryLength];
|
||||
|
||||
/*
|
||||
Try opening the sample file
|
||||
*/
|
||||
[self openFileWithFilePathURL:[NSURL fileURLWithPath:kAudioFileDefault]];
|
||||
}
|
||||
|
||||
@@ -103,53 +81,56 @@
|
||||
- (void)changeVolume:(id)sender
|
||||
{
|
||||
float value = [(UISlider *)sender value];
|
||||
[self.output setVolume:value];
|
||||
[self.player setVolume:value];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
- (void)openFileWithFilePathURL:(NSURL *)filePathURL
|
||||
{
|
||||
// Stop playback
|
||||
[self.output stopPlayback];
|
||||
//
|
||||
// Create the EZAudioPlayer
|
||||
//
|
||||
self.audioFile = [EZAudioFile audioFileWithURL:filePathURL];
|
||||
|
||||
self.audioFile = [EZAudioFile audioFileWithURL:filePathURL delegate:self];
|
||||
self.eof = NO;
|
||||
//
|
||||
// Update the UI
|
||||
//
|
||||
self.filePathLabel.text = filePathURL.lastPathComponent;
|
||||
self.framePositionSlider.maximumValue = (float)self.audioFile.totalFrames;
|
||||
|
||||
// Set the input format from the EZAudioFile on the output
|
||||
[self.output setInputFormat:[self.audioFile clientFormat]];
|
||||
self.positionSlider.maximumValue = (float)self.audioFile.totalFrames;
|
||||
self.volumeSlider.value = [self.player volume];
|
||||
|
||||
//
|
||||
// Plot the whole waveform
|
||||
//
|
||||
self.audioPlot.plotType = EZPlotTypeBuffer;
|
||||
self.audioPlot.shouldFill = YES;
|
||||
self.audioPlot.shouldMirror = YES;
|
||||
|
||||
__weak typeof (self) weakSelf = self;
|
||||
[self.audioFile getWaveformDataWithCompletionBlock:^(float **waveformData,
|
||||
int length)
|
||||
{
|
||||
[weakSelf.audioPlot updateBuffer:waveformData[0]
|
||||
withBufferSize:length];
|
||||
}];
|
||||
{
|
||||
[weakSelf.audioPlot updateBuffer:waveformData[0]
|
||||
withBufferSize:length];
|
||||
}];
|
||||
|
||||
//
|
||||
// Play the audio file
|
||||
//
|
||||
[self.player setAudioFile:self.audioFile];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
- (void)play:(id)sender
|
||||
{
|
||||
if (![self.output isPlaying])
|
||||
if ([self.player isPlaying])
|
||||
{
|
||||
if (self.eof)
|
||||
{
|
||||
[self.audioFile seekToFrame:0];
|
||||
}
|
||||
[self.output startPlayback];
|
||||
[self.player pause];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.output stopPlayback];
|
||||
[self.player play];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +138,39 @@
|
||||
|
||||
- (void)seekToFrame:(id)sender
|
||||
{
|
||||
[self.audioFile seekToFrame:(SInt64)[(UISlider *)sender value]];
|
||||
[self.player seekToFrame:(SInt64)[(UISlider *)sender value]];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#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.audioPlot 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(), ^{
|
||||
if (!weakSelf.positionSlider.touchInside)
|
||||
{
|
||||
weakSelf.positionSlider.value = (float)framePosition;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -186,73 +199,6 @@
|
||||
self.audioPlot.shouldMirror = YES;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma mark - EZAudioFileDelegate
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
- (void)audioFile:(EZAudioFile *)audioFile
|
||||
updatedPosition:(SInt64)framePosition
|
||||
{
|
||||
__weak typeof (self) weakSelf = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (!weakSelf.framePositionSlider.touchInside)
|
||||
{
|
||||
weakSelf.framePositionSlider.value = (float)framePosition;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma mark - EZOutputDataSource
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
- (OSStatus) output:(EZOutput *)output
|
||||
shouldFillAudioBufferList:(AudioBufferList *)audioBufferList
|
||||
withNumberOfFrames:(UInt32)frames
|
||||
timestamp:(const AudioTimeStamp *)timestamp
|
||||
{
|
||||
if (self.audioFile)
|
||||
{
|
||||
UInt32 bufferSize;
|
||||
BOOL eof;
|
||||
[self.audioFile readFrames:frames
|
||||
audioBufferList:audioBufferList
|
||||
bufferSize:&bufferSize
|
||||
eof:&eof];
|
||||
if (eof)
|
||||
{
|
||||
[self.audioFile seekToFrame:0];
|
||||
}
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma mark - EZOutputDelegate
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
- (void) output:(EZOutput *)output
|
||||
playedAudio:(float **)buffer
|
||||
withBufferSize:(UInt32)bufferSize
|
||||
withNumberOfChannels:(UInt32)numberOfChannels
|
||||
{
|
||||
__weak typeof (self) weakSelf = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([self.output isPlaying])
|
||||
{
|
||||
if (weakSelf.audioPlot.plotType == EZPlotTypeBuffer &&
|
||||
weakSelf.audioPlot.shouldFill == YES &&
|
||||
weakSelf.audioPlot.shouldMirror == YES)
|
||||
{
|
||||
weakSelf.audioPlot.shouldFill = NO;
|
||||
weakSelf.audioPlot.shouldMirror = NO;
|
||||
}
|
||||
[weakSelf.audioPlot updateBuffer:buffer[0]
|
||||
withBufferSize:bufferSize];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user