Compare commits

...

41 Commits

Author SHA1 Message Date
Syed Haris Ali 618be0dc70 Last change to CHANGELOG before 0.0.3 release 2014-01-17 14:15:40 -08:00
Syed Haris Ali 579f924aef Added stereo to EZOutput for circular buffer. This only copies the channel over though, need a EZConverter to do this properly to interleave the data 2014-01-17 14:12:03 -08:00
Syed Haris Ali 43418bb825 removed accidental add 2014-01-17 12:59:54 -08:00
Syed Haris Ali f474b55375 Cleaned up a bit 2014-01-17 12:59:37 -08:00
Syed Haris Ali 232b02904c Updated for 0.0.3 release 2014-01-17 12:59:05 -08:00
Syed Haris Ali b093e479d7 Added ability to adjust the resolution of the waveform for the audio file and added getter for audio file's URL 2014-01-17 12:55:39 -08:00
Syed Haris Ali 98707d0cf1 Added adjustable rolling waveform resolution 2014-01-17 12:52:22 -08:00
Syed Haris Ali fc091642d9 Fixed a few bugs related to allocating the proper write buffers for the AudioBufferList and added stereo support 2014-01-17 12:34:31 -08:00
Syed Haris Ali 5cd022a510 Refactored EZMicrophone for readability - broke configuration into smaller functions and organized layout 2014-01-17 12:31:20 -08:00
Syed Haris Ali c8b144667a Cleaned up for 0.0.3 release 2014-01-12 00:08:44 -05:00
Syed Haris Ali 4d0bd00c79 Removed excess logging 2014-01-12 00:07:23 -05:00
Syed Haris Ali fb0e1cff2d Modified example to use custom AudioStreamBasicDescription 2014-01-12 00:05:58 -05:00
Syed Haris Ali 4d2c8f3fef Updated OSX PlayFile example to use custom AudioStreamBasicDescription on EZOutput 2014-01-12 00:04:20 -05:00
Syed Haris Ali 1dd7c7bec9 Accidently deleted EZMicrophone object, added back...whoops 2014-01-11 23:19:50 -05:00
Syed Haris Ali 4622815a19 Updated PlayFile to use custom AudioStreamBasicDescription pulled from file client format 2014-01-11 23:18:36 -05:00
Syed Haris Ali 512f896dff Updated FFT example for memory cleanup 2014-01-11 23:18:00 -05:00
Syed Haris Ali fd837d46ea Updated CHANGELOG to reflect new rolling plot and custom EZMicrophone and EZOutput 2014-01-11 23:16:47 -05:00
Syed Haris Ali 689e004814 Added custom class AudioStreamBasicDescription initializer to output 2014-01-11 22:36:02 -05:00
Syed Haris Ali ef6b6ee5a7 Modified EZPlotTypeRolling to scroll instead of wipe screen 2014-01-11 22:20:35 -05:00
Syed Haris Ali 8d8246c3c6 Added utility functions for AudioStreamBasicDescription, Math (update history and shift array contents), and Plot (shared rolling history update function) 2014-01-11 22:19:02 -05:00
Syed Haris Ali 1dc2fc2ba9 Screwed up something in EZAudioFile memory cleanup, removing floatBuffers cleanup 2014-01-08 23:16:32 -05:00
Syed Haris Ali 2431b25204 Fixed getWaveformData function to not use float converter and added proper memory management to EZAudioFile 2014-01-08 23:03:39 -05:00
Syed Haris Ali 2e9af21099 Merge branch 'master' of https://github.com/syedhali/EZAudio 2014-01-08 22:28:25 -05:00
Syed Haris Ali b06bbb99fb Fixed EZAudioFile and EZOutput to provide true stereo 2014-01-08 22:28:00 -05:00
Syed Haris Ali 2ac8e4ec42 Merge pull request #5 from wdwen/master
EZAudioPlotGLKViewController add _bgcolor member data, record bgcolor. _...
2014-01-04 18:41:15 -08:00
wdwen 6739c70063 remove two call of glClear in glkView:drawInRect: 2014-01-05 10:37:53 +08:00
wdwen ec55542b8d remove bgcolor data member.
add glClear(GL_COLOR_BUFFER_BIT) method at begin of glkView:drawInRect
2014-01-05 10:14:32 +08:00
daiwen 08874048fc EZAudioPlotGLKViewController add _bgcolor member data, record bgcolor. _bgcolor used for hand glkView:drawInRect else condition 2014-01-02 19:13:54 +08:00
Syed Haris Ali cd887d002d Merge branch 'master' of https://github.com/syedhali/EZAudio 2013-12-31 11:15:40 -08:00
Syed Haris Ali 0e274696bf Client format for audio file uses sample rate pulled from file format 2013-12-31 11:15:27 -08:00
Syed Haris Ali 820e0d3f21 Added EZAudioFFTExample to README 2013-12-30 14:54:05 -08:00
Syed Haris Ali a5ff527a3a Merge branch 'master' of https://github.com/syedhali/EZAudio 2013-12-30 14:22:41 -08:00
Syed Haris Ali d725db31bc Added MIT license to example files 2013-12-30 14:21:18 -08:00
Syed Haris Ali b9f80eeee7 Adding in FFT example projects 2013-12-30 14:15:03 -08:00
Syed Haris Ali 54345f2d6e Fixed typo in EZAudioPlotGL readme section 2013-12-30 08:54:42 -08:00
Syed Haris Ali 6cafae6236 Update documentation section 2013-12-25 09:32:59 -08:00
Syed Haris Ali e0c4d3adca Update README.md 2013-12-24 18:45:13 -08:00
Syed Haris Ali b8513ab62d Added Acknowledgements 2013-12-24 18:43:39 -08:00
Syed Haris Ali f31b90a4e2 Adding Cocoapod how to 2013-12-24 00:56:05 -08:00
Syed Haris Ali da4fdb6692 Updated version 2013-12-23 21:48:31 -08:00
Syed Haris Ali 567e0f61e9 Updated podspec 2013-12-23 21:40:22 -08:00
71 changed files with 4402 additions and 509 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "EZAudio"
s.version = "0.0.1"
s.version = "0.0.2"
s.summary = "A simple, intuitive audio framework for iOS and OSX useful for anyone doing audio processing and/or audio-based visualizations."
s.homepage = "http://syedharisali.com/projects/EZAudio/getting-started"
s.screenshots = "https://s3-us-west-1.amazonaws.com/ezaudio-media/EZAudioSummary.png"
@@ -8,7 +8,7 @@ Pod::Spec.new do |s|
s.author = { "Syed Haris Ali" => "syedhali07@gmail.com" }
s.ios.deployment_target = '6.0'
s.osx.deployment_target = '10.8'
s.source = { :git => "https://github.com/syedhali/EZAudio.git", :tag => "0.0.1" }
s.source = { :git => "https://github.com/syedhali/EZAudio.git", :tag => "0.0.2" }
s.source_files = 'EZAudio/*.{h,m,c}'
s.exclude_files = 'EZAudio/VERSION'
s.ios.frameworks = 'AudioToolbox','GLKit'
+66
View File
@@ -66,6 +66,38 @@
+(void)freeBufferList:(AudioBufferList*)bufferList;
#pragma mark - AudioStreamBasicDescription Utilties
///-----------------------------------------------------------
/// @name Creating An AudioStreamBasicDescription
///-----------------------------------------------------------
/**
@param sampleRate The desired sample rate for the AudioStreamBasicDescription
@return A new AudioStreamBasicDescription with the specified format.
*/
+(AudioStreamBasicDescription)monoFloatFormatWithSampleRate:(float)sampleRate;
/**
@param sampleRate The desired sample rate for the AudioStreamBasicDescription
@return A new AudioStreamBasicDescription with the specified format.
*/
+(AudioStreamBasicDescription)monoCanonicalFormatWithSampleRate:(float)sampleRate;
/**
@param sampleRate The desired sample rate for the AudioStreamBasicDescription
@return A new AudioStreamBasicDescription with the specified format.
*/
+(AudioStreamBasicDescription)stereoCanonicalNonInterleavedFormatWithSampleRate:(float)sampleRate;
/**
@param sampleRate The desired sample rate for the AudioStreamBasicDescription
@return A new AudioStreamBasicDescription with the specified format.
*/
+(AudioStreamBasicDescription)stereoFloatInterleavedFormatWithSampleRate:(float)sampleRate;
///-----------------------------------------------------------
/// @name AudioStreamBasicDescription Utilities
///-----------------------------------------------------------
@@ -91,6 +123,28 @@
/// @name Math Utilities
///-----------------------------------------------------------
/**
Appends an array of values to a history buffer and performs an internal shift to add the values to the tail and removes the same number of values from the head.
@param buffer A float array of values to append to the tail of the history buffer
@param bufferLength The length of the float array being appended to the history buffer
@param scrollHistory The target history buffer in which to append the values
@param scrollHistoryLength The length of the target history buffer
*/
+(void)appendBufferAndShift:(float*)buffer
withBufferSize:(int)bufferLength
toScrollHistory:(float*)scrollHistory
withScrollHistorySize:(int)scrollHistoryLength;
/**
Appends a value to a history buffer and performs an internal shift to add the value to the tail and remove the 0th value.
@param value The float value to append to the history array
@param scrollHistory The target history buffer in which to append the values
@param scrollHistoryLength The length of the target history buffer
*/
+(void) appendValue:(float)value
toScrollHistory:(float*)scrollHistory
withScrollHistorySize:(int)scrollHistoryLength;
/**
Maps a value from one coordinate system into another one. Takes in the current value to map, the minimum and maximum values of the first coordinate system, and the minimum and maximum values of the second coordinate system and calculates the mapped value in the second coordinate system's constraints.
@param value The value expressed in the first coordinate system
@@ -128,6 +182,18 @@
+(void)checkResult:(OSStatus)result
operation:(const char*)operation;
#pragma mark - Plot Utility
///-----------------------------------------------------------
/// @name Plot Utility
///-----------------------------------------------------------
+(void)updateScrollHistory:(float**)scrollHistory
withLength:(int)scrollHistoryLength
atIndex:(int*)index
withBuffer:(float*)buffer
withBufferSize:(int)bufferSize
isResolutionChanging:(BOOL*)isChanging;
#pragma mark - TPCircularBuffer Utility
///-----------------------------------------------------------
/// @name TPCircularBuffer Utility
+122
View File
@@ -44,6 +44,64 @@
}
#pragma mark - AudioStreamBasicDescription Utility
/// AudioStreamFormatDescription Helpers
+(AudioStreamBasicDescription)monoFloatFormatWithSampleRate:(float)sampleRate {
AudioStreamBasicDescription asbd;
UInt32 byteSize = sizeof(AudioUnitSampleType);
asbd.mBitsPerChannel = 8 * byteSize;
asbd.mBytesPerFrame = byteSize;
asbd.mBytesPerPacket = byteSize;
asbd.mChannelsPerFrame = 1;
asbd.mFormatFlags = kAudioFormatFlagIsPacked|kAudioFormatFlagIsFloat;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFramesPerPacket = 1;
asbd.mSampleRate = sampleRate;
return asbd;
}
+(AudioStreamBasicDescription)monoCanonicalFormatWithSampleRate:(float)sampleRate {
AudioStreamBasicDescription asbd;
UInt32 byteSize = sizeof(AudioUnitSampleType);
asbd.mBitsPerChannel = 8 * byteSize;
asbd.mBytesPerFrame = byteSize;
asbd.mBytesPerPacket = byteSize;
asbd.mChannelsPerFrame = 1;
asbd.mFormatFlags = kAudioFormatFlagsCanonical|kAudioFormatFlagIsNonInterleaved;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFramesPerPacket = 1;
asbd.mSampleRate = sampleRate;
return asbd;
}
+(AudioStreamBasicDescription)stereoCanonicalNonInterleavedFormatWithSampleRate:(float)sampleRate {
AudioStreamBasicDescription asbd;
UInt32 byteSize = sizeof(AudioUnitSampleType);
asbd.mBitsPerChannel = 8 * byteSize;
asbd.mBytesPerFrame = byteSize;
asbd.mBytesPerPacket = byteSize;
asbd.mChannelsPerFrame = 2;
asbd.mFormatFlags = kAudioFormatFlagsCanonical|kAudioFormatFlagIsNonInterleaved;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFramesPerPacket = 1;
asbd.mSampleRate = sampleRate;
return asbd;
}
+(AudioStreamBasicDescription)stereoFloatInterleavedFormatWithSampleRate:(float)sampleRate {
AudioStreamBasicDescription asbd;
UInt32 byteSize = sizeof(AudioUnitSampleType);
asbd.mBitsPerChannel = 8 * byteSize;
asbd.mBytesPerFrame = 2 * byteSize;
asbd.mBytesPerPacket = 2 * byteSize;
asbd.mChannelsPerFrame = 2;
asbd.mFormatFlags = kAudioFormatFlagIsPacked|kAudioFormatFlagIsFloat;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFramesPerPacket = 1;
asbd.mSampleRate = sampleRate;
return asbd;
}
+(void)printASBD:(AudioStreamBasicDescription)asbd {
char formatIDString[5];
UInt32 formatID = CFSwapInt32HostToBig(asbd.mFormatID);
@@ -94,6 +152,35 @@
}
#pragma mark - Math Utility
+(void)appendBufferAndShift:(float*)buffer
withBufferSize:(int)bufferLength
toScrollHistory:(float*)scrollHistory
withScrollHistorySize:(int)scrollHistoryLength {
NSAssert(scrollHistoryLength>=bufferLength,@"Scroll history array length must be greater buffer length");
NSAssert(scrollHistoryLength>0,@"Scroll history array length must be greater than 0");
NSAssert(bufferLength>0,@"Buffer array length must be greater than 0");
int shiftLength = scrollHistoryLength - bufferLength;
size_t floatByteSize = sizeof(float);
size_t shiftByteSize = shiftLength * floatByteSize;
size_t bufferByteSize = bufferLength * floatByteSize;
memmove(&scrollHistory[0],
&scrollHistory[bufferLength],
shiftByteSize);
memmove(&scrollHistory[shiftLength],
&buffer[0],
bufferByteSize);
}
+(void) appendValue:(float)value
toScrollHistory:(float*)scrollHistory
withScrollHistorySize:(int)scrollHistoryLength {
float val[1]; val[0] = value;
[self appendBufferAndShift:val
withBufferSize:1
toScrollHistory:scrollHistory
withScrollHistorySize:scrollHistoryLength];
}
+(float)MAP:(float)value
leftMin:(float)leftMin
leftMax:(float)leftMax
@@ -113,6 +200,40 @@
return sqrtf( sum / bufferSize );
}
#pragma mark - Plot Utility
+(void)updateScrollHistory:(float **)scrollHistory
withLength:(int)scrollHistoryLength
atIndex:(int*)index
withBuffer:(float *)buffer
withBufferSize:(int)bufferSize
isResolutionChanging:(BOOL*)isChanging {
//
size_t floatByteSize = sizeof(float);
//
if( *scrollHistory == NULL ){
// Create the history buffer
*scrollHistory = (float*)calloc(kEZAudioPlotMaxHistoryBufferLength,floatByteSize);
}
//
if( !*isChanging ){
float rms = [EZAudio RMS:buffer length:bufferSize];
if( *index < scrollHistoryLength ){
float *hist = *scrollHistory;
hist[*index] = rms;
(*index)++;
}
else {
[EZAudio appendValue:rms
toScrollHistory:*scrollHistory
withScrollHistorySize:scrollHistoryLength];
}
}
}
#pragma mark - TPCircularBuffer Utility
+(void)circularBuffer:(TPCircularBuffer *)circularBuffer withSize:(int)size {
TPCircularBufferInit(circularBuffer,size);
@@ -127,6 +248,7 @@
+(void)freeCircularBuffer:(TPCircularBuffer *)circularBuffer {
TPCircularBufferClear(circularBuffer);
TPCircularBufferCleanup(circularBuffer);
}
@end
+17
View File
@@ -76,6 +76,11 @@ typedef void (^WaveformDataCompletionBlock)(float *waveformData, UInt32 length);
*/
@property (nonatomic,assign) id<EZAudioFileDelegate> audioFileDelegate;
/**
The resolution of the waveform data. This value specifies how the recommendedDrawingFrameRate chooses itself. A low value like 128 will render a waveform containing 128 points representing a low resolution waveform while a high value like 4096 will render a high quality waveform. Higher resolutions provide more detail, but take more work to render in the audio waveform plots (EZAudioPlot or EZAudioPlotGL) while lower resolutions providel less detail, but work better for displaying many at a time (like in a UITableView)
*/
@property (nonatomic,assign) UInt32 waveformResolution;
#pragma mark - Initializers
///-----------------------------------------------------------
/// @name Initializers
@@ -191,11 +196,23 @@ typedef void (^WaveformDataCompletionBlock)(float *waveformData, UInt32 length);
*/
-(SInt64)totalFrames;
/**
Provides the NSURL for the audio file.
@return An NSURL representing the path of the EZAudioFile instance.
*/
-(NSURL*)url;
#pragma mark - Helpers
///-----------------------------------------------------------
/// @name Manipulating The Audio Data
///-----------------------------------------------------------
/**
Tells the caller whether the EZAudioFile has cached waveform data that was loaded via the getWaveformDataWithCompletionBlock: function.
* @return A BOOL indicating whether there is cached waveform data
*/
-(BOOL)hasLoadedAudioData;
/**
Asynchronously pulls the waveform amplitude data into a float array for the receiver.
@param waveformDataCompletionBlock A WaveformDataCompletionBlock that executes when the waveform data has been extracted. Provides the waveform data as a float array and the length of the array.
+59 -24
View File
@@ -27,6 +27,8 @@
#import "EZAudio.h"
#define kEZAudioFileWaveformDefaultResolution (1024)
@interface EZAudioFile (){
// Reading from the audio file
@@ -50,6 +52,7 @@
@implementation EZAudioFile
@synthesize audioFileDelegate = _audioFileDelegate;
@synthesize waveformResolution = _waveformResolution;
#pragma mark - Initializers
-(EZAudioFile*)initWithURL:(NSURL*)url {
@@ -108,7 +111,6 @@
UInt32 size = sizeof(_fileFormat);
[EZAudio checkResult:ExtAudioFileGetProperty(_audioFile,kExtAudioFileProperty_FileDataFormat, &size, &_fileFormat)
operation:"Failed to get audio stream basic description of input file"];
[EZAudio printASBD:_fileFormat];
// Try pulling the total frame size
size = sizeof(_totalFrames);
@@ -119,15 +121,17 @@
_totalDuration = _totalFrames / _fileFormat.mSampleRate;
// Set the client format on the stream
_clientFormat.mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);
_clientFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
_clientFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
_clientFormat.mChannelsPerFrame = 1;
_clientFormat.mFormatFlags = kAudioFormatFlagsCanonical | kAudioFormatFlagIsNonInterleaved;
_clientFormat.mFormatID = kAudioFormatLinearPCM;
_clientFormat.mFramesPerPacket = 1;
_clientFormat.mSampleRate = 44100;
switch (_fileFormat.mChannelsPerFrame) {
case 1:
_clientFormat = [EZAudio monoFloatFormatWithSampleRate:_fileFormat.mSampleRate];
break;
case 2:
_clientFormat = [EZAudio stereoFloatInterleavedFormatWithSampleRate:_fileFormat.mSampleRate];
break;
default:
break;
}
[EZAudio checkResult:ExtAudioFileSetProperty(_audioFile,
kExtAudioFileProperty_ClientDataFormat,
sizeof (AudioStreamBasicDescription),
@@ -142,6 +146,12 @@
_floatBuffers[i] = (float*)malloc(outputBufferSize);
}
// There's no waveform data yet
_waveformData = NULL;
// Set the default resolution for the waveform data
_waveformResolution = kEZAudioFileWaveformDefaultResolution;
}
#pragma mark - Events
@@ -154,8 +164,8 @@
UInt32 outputBufferSize = 32 * frames; // 32 KB
audioBufferList->mNumberBuffers = 1;
audioBufferList->mBuffers[0].mNumberChannels = _clientFormat.mChannelsPerFrame;
audioBufferList->mBuffers[0].mDataByteSize = outputBufferSize;
audioBufferList->mBuffers[0].mData = (AudioUnitSampleType*)malloc(sizeof(AudioUnitSampleType*)*outputBufferSize);
audioBufferList->mBuffers[0].mDataByteSize = _clientFormat.mChannelsPerFrame*outputBufferSize;
audioBufferList->mBuffers[0].mData = (AudioUnitSampleType*)malloc(_clientFormat.mChannelsPerFrame*sizeof(AudioUnitSampleType*)*outputBufferSize);
[EZAudio checkResult:ExtAudioFileRead(_audioFile,
&frames,
audioBufferList)
@@ -191,21 +201,26 @@
}
#pragma mark - Getters
-(BOOL)hasLoadedAudioData {
return _waveformData != NULL;
}
-(void)getWaveformDataWithCompletionBlock:(WaveformDataCompletionBlock)waveformDataCompletionBlock {
SInt64 currentFramePosition = _frameIndex;
if( _waveformData ){
if( _waveformData != NULL ){
waveformDataCompletionBlock( _waveformData, _waveformTotalBuffers );
return;
}
_waveformFrameRate = [self recommendedDrawingFrameRate];
_waveformTotalBuffers = [self minBuffersWithFrameRate:_waveformFrameRate];
_waveformData = (float*)malloc(sizeof(float)*_waveformTotalBuffers);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0ul), ^{
_waveformFrameRate = [self recommendedDrawingFrameRate];
_waveformTotalBuffers = [self minBuffersWithFrameRate:_waveformFrameRate];
_waveformData = (float*)malloc(sizeof(float)*_waveformTotalBuffers);
for( int i = 0; i < _waveformTotalBuffers; i++ ){
@@ -218,8 +233,8 @@
UInt32 outputBufferSize = 32 * _waveformFrameRate; // 32 KB
bufferList->mNumberBuffers = 1;
bufferList->mBuffers[0].mNumberChannels = _clientFormat.mChannelsPerFrame;
bufferList->mBuffers[0].mDataByteSize = outputBufferSize;
bufferList->mBuffers[0].mData = (AudioUnitSampleType*)malloc(sizeof(AudioUnitSampleType*)*outputBufferSize);
bufferList->mBuffers[0].mDataByteSize = _clientFormat.mChannelsPerFrame*outputBufferSize;
bufferList->mBuffers[0].mData = (AudioUnitSampleType*)malloc(_clientFormat.mChannelsPerFrame*sizeof(AudioUnitSampleType*)*outputBufferSize);
// Read in the specified number of frames
[EZAudio checkResult:ExtAudioFileRead(_audioFile,
@@ -230,11 +245,8 @@
eof = _waveformFrameRate == 0;
_frameIndex += _waveformFrameRate;
// Convert to floats
AEFloatConverterToFloat(_floatConverter,bufferList,_floatBuffers,_waveformFrameRate);
// Calculate RMS of each buffer
float rms = [EZAudio RMS:_floatBuffers[0]
float rms = [EZAudio RMS:bufferList->mBuffers[0].mData
length:bufferSize];
_waveformData[i] = rms;
@@ -277,6 +289,21 @@
return _totalFrames;
}
-(NSURL *)url {
return (__bridge NSURL*)_sourceURL;
}
#pragma mark - Setters
-(void)setWaveformResolution:(UInt32)waveformResolution {
if( _waveformResolution != waveformResolution ){
_waveformResolution = waveformResolution;
if( _waveformData ){
free(_waveformData);
_waveformData = NULL;
}
}
}
#pragma mark - Helpers
-(UInt32)minBuffersWithFrameRate:(UInt32)frameRate {
frameRate = frameRate > 0 ? frameRate : 1;
@@ -284,14 +311,22 @@
}
-(UInt32)recommendedDrawingFrameRate {
return (UInt32) _totalFrames / 2057 - 1;
return (UInt32) _totalFrames / _waveformResolution - 1;
}
#pragma mark - Cleanup
-(void)dealloc {
if( _waveformData ){
free(_waveformData);
_waveformData = NULL;
}
// if( _floatBuffers ){
// free(_floatBuffers);
// _floatBuffers = NULL;
// }
_frameIndex = 0;
_waveformFrameRate = 0;
_waveformTotalBuffers = 0;
[EZAudio checkResult:ExtAudioFileDispose(_audioFile)
operation:"Failed to dispose of extended audio file."];
}
+15 -4
View File
@@ -28,10 +28,9 @@
@class EZAudio;
/**
The default since of the rolling audio plot. TODO: In future release make this real-time adjustable.
*/
#define kEZAudioPlotHistoryBufferSize 1024
#define kEZAudioPlotMaxHistoryBufferLength (8192)
#define kEZAudioPlotDefaultHistoryBufferLength (1024)
/**
`EZAudioPlot`, a subclass of `EZPlot`, is a cross-platform (iOS and OSX) class that plots an audio waveform using Core Graphics.
@@ -48,4 +47,16 @@
*/
@interface EZAudioPlot : EZPlot
#pragma mark - Adjust Resolution
///-----------------------------------------------------------
/// @name Adjusting The Resolution
///-----------------------------------------------------------
/**
Sets the length of the rolling history display. Can grow or shrink the display up to the maximum size specified by the kEZAudioPlotMaxHistoryBufferLength macro. Will return the actual set value, which will be either the given value if smaller than the kEZAudioPlotMaxHistoryBufferLength or kEZAudioPlotMaxHistoryBufferLength if a larger value is attempted to be set.
@param historyLength The new length of the rolling history buffer.
@return The new value equal to the historyLength or the kEZAudioPlotMaxHistoryBufferLength.
*/
-(int)setRollingHistoryLength:(int)historyLength;
@end
+48 -39
View File
@@ -27,11 +27,16 @@
#import "EZAudio.h"
#define kCircularBufferSizeTemp 512
@interface EZAudioPlot () {
BOOL _hasData;
TPCircularBuffer _historyBuffer;
// BOOL _hasData;
// TPCircularBuffer _historyBuffer;
// Rolling History
BOOL _setMaxLength;
float *_scrollHistory;
int _scrollHistoryIndex;
UInt32 _scrollHistoryLength;
BOOL _changingHistorySize;
CGPoint *_sampleData;
UInt32 _sampleLength;
@@ -87,6 +92,8 @@
self.plotType = EZPlotTypeRolling;
self.shouldMirror = NO;
self.shouldFill = NO;
_scrollHistory = NULL;
_scrollHistoryLength = kEZAudioPlotDefaultHistoryBufferLength;
}
#pragma mark - Setters
@@ -139,7 +146,7 @@
_sampleLength = length;
for(int i = 0; i < length; i++) {
the_sampleData[i] = i == 0 || i == length - 1 ? 0 : the_sampleData[i];
the_sampleData[i] = i == 0 ? 0 : the_sampleData[i];
_sampleData[i] = CGPointMake(i,the_sampleData[i] * _gain);
}
@@ -150,39 +157,18 @@
-(void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize {
if( _plotType == EZPlotTypeRolling ){
// Initialize the circular buffer
!_hasData ? TPCircularBufferInit(&_historyBuffer,kCircularBufferSizeTemp) : 0;
_hasData = YES;
// Initialize
_sampleLength = bufferSize;
// Copy into the circular buffer
float rmsValue = [EZAudio RMS:buffer length:bufferSize];
float snapshot[1];
snapshot[0] = rmsValue;
// self.rmsLabel.text = [NSString stringWithFormat:@"RMS: %.4f",rmsValue];
BOOL result = TPCircularBufferProduceBytes(&_historyBuffer,
snapshot,
sizeof(snapshot));
if(result){
// Populate the graph
int32_t availableBytes;
float *cBuf = TPCircularBufferTail(&_historyBuffer,&availableBytes);
for(int i = 0; i < kCircularBufferSizeTemp; i++) {
if( availableBytes == kCircularBufferSizeTemp*sizeof(float) ){
cBuf[i] = 0.0f;
}
}
[self _setSampleData:cBuf
length:kCircularBufferSizeTemp];
if( availableBytes == kCircularBufferSizeTemp*sizeof(float) ){
TPCircularBufferConsume(&_historyBuffer,kCircularBufferSizeTemp*sizeof(float));
}
}
else {
NSLog(@"Failed to copy bytes to circular buffer 1");
}
// Update the scroll history datasource
[EZAudio updateScrollHistory:&_scrollHistory
withLength:_scrollHistoryLength
atIndex:&_scrollHistoryIndex
withBuffer:buffer
withBufferSize:bufferSize
isResolutionChanging:&_changingHistorySize];
//
[self _setSampleData:_scrollHistory
length:(!_setMaxLength?kEZAudioPlotMaxHistoryBufferLength:_scrollHistoryLength)];
_setMaxLength = YES;
}
else if( _plotType == EZPlotTypeBuffer ){
@@ -228,12 +214,14 @@
#endif
if(_sampleLength > 0) {
_sampleData[_sampleLength-1] = CGPointMake(_sampleLength-1,0.0f);
CGMutablePathRef halfPath = CGPathCreateMutable();
CGPathAddLines(halfPath,
NULL,
_sampleData,
_sampleLength);
CGMutablePathRef path = CGPathCreateMutable();
double xscale = (frame.size.width) / (float)_sampleLength;
@@ -278,7 +266,28 @@
#elif TARGET_OS_MAC
[[NSGraphicsContext currentContext] restoreGraphicsState];
#endif
}
#pragma mark - Adjust Resolution
-(int)setRollingHistoryLength:(int)historyLength {
historyLength = MIN(historyLength,kEZAudioPlotMaxHistoryBufferLength);
size_t floatByteSize = sizeof(float);
_changingHistorySize = YES;
if( _scrollHistoryLength != historyLength ){
_scrollHistoryLength = historyLength;
}
_scrollHistory = realloc(_scrollHistory,_scrollHistoryLength*floatByteSize);
if( _scrollHistoryIndex < _scrollHistoryLength ){
memset(&_scrollHistory[_scrollHistoryIndex],
0,
(_scrollHistoryLength-_scrollHistoryIndex)*floatByteSize);
}
else {
_scrollHistoryIndex = _scrollHistoryLength;
}
_changingHistorySize = NO;
return historyLength;
}
-(void)dealloc {
free(_sampleData);
+12
View File
@@ -124,6 +124,18 @@ typedef struct {
#endif
#pragma mark - Adjust Resolution
///-----------------------------------------------------------
/// @name Adjusting The Resolution
///-----------------------------------------------------------
/**
Sets the length of the rolling history display. Can grow or shrink the display up to the maximum size specified by the kEZAudioPlotMaxHistoryBufferLength macro. Will return the actual set value, which will be either the given value if smaller than the kEZAudioPlotMaxHistoryBufferLength or kEZAudioPlotMaxHistoryBufferLength if a larger value is attempted to be set.
@param historyLength The new length of the rolling history buffer.
@return The new value equal to the historyLength or the kEZAudioPlotMaxHistoryBufferLength.
*/
-(int)setRollingHistoryLength:(int)historyLength;
#pragma mark - Shared Methods
///-----------------------------------------------------------
/// @name Shared OpenGL Methods
+83 -36
View File
@@ -54,9 +54,17 @@
UInt32 _bufferPlotGraphSize;
UInt32 _rollingPlotGraphSize;
// History buffer
UInt32 _historyIndex;
float _historyBuffer[kEZAudioPlotHistoryBufferSize];
// Rolling History
BOOL _setMaxLength;
float *_scrollHistory;
int _scrollHistoryIndex;
UInt32 _scrollHistoryLength;
BOOL _changingHistorySize;
// Copied buffer data
float *_copiedBuffer;
UInt32 _copiedBufferSize;
}
@property (nonatomic,assign,readonly) EZAudioPlotGLDrawType drawingType;
@property (nonatomic,strong) GLKBaseEffect *baseEffect;
@@ -105,15 +113,14 @@
#pragma mark - Initialize Properties Here
-(void)initializeView {
#if TARGET_OS_IPHONE
// Initialize the subview controller
_glViewController = [[EZAudioPlotGLKViewController alloc] init];
_glViewController.view.frame = self.frame;
_glViewController.view.frame = self.bounds;
[self insertSubview:self.glViewController.view atIndex:0];
#elif TARGET_OS_MAC
_copiedBuffer = NULL;
#endif
// Set the default properties
self.gain = 1.0;
self.plotType = EZPlotTypeBuffer;
@@ -121,10 +128,11 @@
self.backgroundColor = [UIColor colorWithRed:0.796 green:0.749 blue:0.663 alpha:1];
self.color = [UIColor colorWithRed:0.481 green:0.548 blue:0.637 alpha:1];
#elif TARGET_OS_MAC
_scrollHistory = NULL;
_scrollHistoryLength = kEZAudioPlotDefaultHistoryBufferLength;
#endif
self.shouldFill = NO;
self.shouldMirror = NO;
}
#pragma mark - Setters
@@ -199,15 +207,23 @@
[self.glViewController updateBuffer:buffer
withBufferSize:bufferSize];
#elif TARGET_OS_MAC
if( _copiedBuffer == NULL ){
_copiedBuffer = (float*)malloc(bufferSize*sizeof(float));
}
_copiedBufferSize = bufferSize;
// Copy the buffer
memcpy(_copiedBuffer,
buffer,
bufferSize*sizeof(float));
// Draw based on plot type
switch(_plotType) {
case EZPlotTypeBuffer:
[self _updateBufferPlotBufferWithAudioReceived:buffer
withBufferSize:bufferSize];
[self _updateBufferPlotBufferWithAudioReceived:_copiedBuffer
withBufferSize:_copiedBufferSize];
break;
case EZPlotTypeRolling:
[self _updateRollingPlotBufferWithAudioReceived:buffer
withBufferSize:bufferSize];
[self _updateRollingPlotBufferWithAudioReceived:_copiedBuffer
withBufferSize:_copiedBufferSize];
break;
default:
break;
@@ -430,34 +446,34 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink,
// If starting with a VBO of half of our max size make sure we initialize it to anticipate
// a filled graph (which needs 2 * bufferSize) to allocate its resources properly
if( !_hasRollingPlotData && _drawingType == EZAudioPlotGLDrawTypeLineStrip ){
EZAudioPlotGLPoint maxGraph[2*kEZAudioPlotHistoryBufferSize];
EZAudioPlotGLPoint maxGraph[2*kEZAudioPlotMaxHistoryBufferLength];
glBufferData(GL_ARRAY_BUFFER, sizeof(maxGraph), maxGraph, GL_STREAM_DRAW );
_hasRollingPlotData = YES;
}
// Setup the plot
_rollingPlotGraphSize = [EZAudioPlotGL graphSizeForDrawingType:_drawingType
withBufferSize:kEZAudioPlotHistoryBufferSize];
withBufferSize:_scrollHistoryLength];
// Fill the graph with data
EZAudioPlotGLPoint graph[_rollingPlotGraphSize];
// Update the history buffer
_historyBuffer[_historyIndex] = [EZAudio RMS:buffer length:bufferSize];
if( _historyIndex == kEZAudioPlotHistoryBufferSize - 1 ){
_historyIndex = 0;
for(int i = 0; i < kEZAudioPlotHistoryBufferSize; i++) _historyBuffer[i] = 0.0f;
}
else {
_historyIndex++;
}
// Update the scroll history datasource
[EZAudio updateScrollHistory:&_scrollHistory
withLength:_scrollHistoryLength
atIndex:&_scrollHistoryIndex
withBuffer:buffer
withBufferSize:bufferSize
isResolutionChanging:&_changingHistorySize];
// Fill in graph data
[EZAudioPlotGL fillGraph:graph
withGraphSize:_rollingPlotGraphSize
forDrawingType:_drawingType
withBuffer:_historyBuffer
withBufferSize:kEZAudioPlotHistoryBufferSize
withBuffer:_scrollHistory
withBufferSize:_scrollHistoryLength
withGain:self.gain];
// Update the drawing
@@ -486,16 +502,18 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink,
// Draw frame
glClear(GL_COLOR_BUFFER_BIT);
// Plot either a buffer plot or a rolling plot
switch(_plotType) {
case EZPlotTypeBuffer:
[self _drawBufferPlot];
break;
case EZPlotTypeRolling:
[self _drawRollingPlot];
break;
default:
break;
if( _hasBufferPlotData || _hasRollingPlotData ){
// Plot either a buffer plot or a rolling plot
switch(_plotType) {
case EZPlotTypeBuffer:
[self _drawBufferPlot];
break;
case EZPlotTypeRolling:
[self _drawRollingPlot];
break;
default:
break;
}
}
// Flush and unlock
@@ -623,9 +641,39 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink,
// when it encounters something that has been release
CVDisplayLinkStop(_displayLink);
CVDisplayLinkRelease(_displayLink);
if( _copiedBuffer != NULL ){
free( _copiedBuffer );
}
}
#endif
#pragma mark - Adjust Resolution
-(int)setRollingHistoryLength:(int)historyLength {
#if TARGET_OS_IPHONE
return [self.glViewController setRollingHistoryLength:historyLength];
#elif TARGET_OS_MAC
historyLength = MIN(historyLength,kEZAudioPlotMaxHistoryBufferLength);
size_t floatByteSize = sizeof(float);
_changingHistorySize = YES;
if( _scrollHistoryLength != historyLength ){
_scrollHistoryLength = historyLength;
}
_scrollHistory = realloc(_scrollHistory,_scrollHistoryLength*floatByteSize);
if( _scrollHistoryIndex < _scrollHistoryLength ){
memset(&_scrollHistory[_scrollHistoryIndex],
0,
(_scrollHistoryLength-_scrollHistoryIndex)*floatByteSize);
}
else {
_scrollHistoryIndex = _scrollHistoryLength;
}
_changingHistorySize = NO;
return historyLength;
#endif
return kEZAudioPlotDefaultHistoryBufferLength;
}
#pragma mark - Graph Methods
+(void)fillGraph:(EZAudioPlotGLPoint*)graph
withGraphSize:(UInt32)graphSize
@@ -648,8 +696,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink,
else if( drawingType == EZAudioPlotGLDrawTypeTriangleStrip ) {
// graph size = 2 * buffer size to draw triangles and fill regions properly
for(int i = 0; i < graphSize; i+=2){
int bufferIndex = (int)[EZAudio
MAP:i
int bufferIndex = (int)[EZAudio MAP:i
leftMin:0
leftMax:graphSize
rightMin:0
+12
View File
@@ -80,6 +80,18 @@
*/
@property (nonatomic,assign,setter=setShouldMirror:) BOOL shouldMirror;
#pragma mark - Adjust Resolution
///-----------------------------------------------------------
/// @name Adjusting The Resolution
///-----------------------------------------------------------
/**
Sets the length of the rolling history display. Can grow or shrink the display up to the maximum size specified by the kEZAudioPlotMaxHistoryBufferLength macro. Will return the actual set value, which will be either the given value if smaller than the kEZAudioPlotMaxHistoryBufferLength or kEZAudioPlotMaxHistoryBufferLength if a larger value is attempted to be set.
@param historyLength The new length of the rolling history buffer.
@return The new value equal to the historyLength or the kEZAudioPlotMaxHistoryBufferLength.
*/
-(int)setRollingHistoryLength:(int)historyLength;
#pragma mark - Get Samples
///-----------------------------------------------------------
/// @name Updating The Plot
+48 -22
View File
@@ -42,9 +42,12 @@
UInt32 _bufferPlotGraphSize;
UInt32 _rollingPlotGraphSize;
// History buffer
UInt32 _historyIndex;
float _historyBuffer[kEZAudioPlotHistoryBufferSize];
// Rolling History
BOOL _setMaxLength;
float *_scrollHistory;
int _scrollHistoryIndex;
UInt32 _scrollHistoryLength;
BOOL _changingHistorySize;
}
@end
@@ -88,6 +91,8 @@
self.baseEffect = [[GLKBaseEffect alloc] init];
self.baseEffect.useConstantColor = GL_TRUE;
self.preferredFramesPerSecond = 60;
_scrollHistory = NULL;
_scrollHistoryLength = kEZAudioPlotDefaultHistoryBufferLength;
}
#pragma mark - View Did Load
@@ -121,6 +126,27 @@
}
#pragma mark - Adjust Resolution
-(int)setRollingHistoryLength:(int)historyLength {
historyLength = MIN(historyLength,kEZAudioPlotMaxHistoryBufferLength);
size_t floatByteSize = sizeof(float);
_changingHistorySize = YES;
if( _scrollHistoryLength != historyLength ){
_scrollHistoryLength = historyLength;
}
_scrollHistory = realloc(_scrollHistory,_scrollHistoryLength*floatByteSize);
if( _scrollHistoryIndex < _scrollHistoryLength ){
memset(&_scrollHistory[_scrollHistoryIndex],
0,
(_scrollHistoryLength-_scrollHistoryIndex)*floatByteSize);
}
else {
_scrollHistoryIndex = _scrollHistoryLength;
}
_changingHistorySize = NO;
return historyLength;
}
#pragma mark - Get Samples
-(void)updateBuffer:(float *)buffer
withBufferSize:(UInt32)bufferSize {
@@ -191,35 +217,35 @@
// If starting with a VBO of half of our max size make sure we initialize it to anticipate
// a filled graph (which needs 2 * bufferSize) to allocate its resources properly
if( !_hasRollingPlotData && _drawingType == EZAudioPlotGLDrawTypeLineStrip ){
EZAudioPlotGLPoint maxGraph[2*kEZAudioPlotHistoryBufferSize];
EZAudioPlotGLPoint maxGraph[2*kEZAudioPlotMaxHistoryBufferLength];
glBufferData(GL_ARRAY_BUFFER, sizeof(maxGraph), maxGraph, GL_STREAM_DRAW );
_hasRollingPlotData = YES;
}
// Setup the plot
_rollingPlotGraphSize = [EZAudioPlotGL graphSizeForDrawingType:_drawingType
withBufferSize:kEZAudioPlotHistoryBufferSize];
withBufferSize:_scrollHistoryLength];
// Fill the graph with data
EZAudioPlotGLPoint graph[_rollingPlotGraphSize];
// Update the history buffer
_historyBuffer[_historyIndex] = [EZAudio RMS:buffer length:bufferSize];
if( _historyIndex == kEZAudioPlotHistoryBufferSize - 1 ){
_historyIndex = 0;
for(int i = 0; i < kEZAudioPlotHistoryBufferSize; i++) _historyBuffer[i] = 0.0f;
}
else {
_historyIndex++;
}
// Update the scroll history datasource
[EZAudio updateScrollHistory:&_scrollHistory
withLength:_scrollHistoryLength
atIndex:&_scrollHistoryIndex
withBuffer:buffer
withBufferSize:bufferSize
isResolutionChanging:&_changingHistorySize];
// Fill in graph data
[EZAudioPlotGL fillGraph:graph
withGraphSize:_rollingPlotGraphSize
forDrawingType:_drawingType
withBuffer:_historyBuffer
withBufferSize:kEZAudioPlotHistoryBufferSize
withGain:self.gain];
withGraphSize:_rollingPlotGraphSize
forDrawingType:_drawingType
withBuffer:_scrollHistory
withBufferSize:_scrollHistoryLength
withGain:self.gain];
// Update the drawing
if( !_hasRollingPlotData ){
@@ -234,13 +260,13 @@
#pragma mark - Drawing
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
// Clear the context
glClear(GL_COLOR_BUFFER_BIT);
if( _hasBufferPlotData || _hasRollingPlotData ){
// Prepare the effect for drawing
[self.baseEffect prepareToDraw];
// Clear the context
glClear(GL_COLOR_BUFFER_BIT);
// Plot either a buffer plot or a rolling plot
switch(_plotType) {
case EZPlotTypeBuffer:
+49 -8
View File
@@ -119,17 +119,35 @@
*/
-(EZMicrophone*)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate;
/**
Creates an instance of the EZMicrophone with a custom AudioStreamBasicDescription and provides the caller to specify a delegate to respond to the audioReceived callback. This will not start fetching the audio until startFetchingAudio has been called. Use initWithMicrophoneDelegate:startsImmediately: to instantiate this class and immediately start fetching audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
-(EZMicrophone*)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription;
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
-(EZMicrophone*)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
startsImmediately:(BOOL)startsImmediately;
/**
Creates an instance of the EZMicrophone with a custom AudioStreamBasicDescription and provides the caller with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
-(EZMicrophone*)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription
startsImmediately:(BOOL)startsImmediately;
#pragma mark - Class Initializers
///-----------------------------------------------------------
/// @name Class Initializers
@@ -137,20 +155,19 @@
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback. This will not start fetching the audio until startFetchingAudio has been called. Use microphoneWithDelegate:startsImmediately: to instantiate this class and immediately start fetching audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@return An instance of the EZMicrophone class. This should be declared as a strong property!
*/
+(EZMicrophone*)microphoneWithDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate;
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback. This will not start fetching the audio until startFetchingAudio has been called. Use microphoneWithDelegate:startsImmediately: to instantiate this class and immediately start fetching audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@return An instance of the EZMicrophone class. This should be declared as a strong property!
*/
+(EZMicrophone*)microphoneWithDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription;
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@@ -162,6 +179,18 @@
+(EZMicrophone*)microphoneWithDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
startsImmediately:(BOOL)startsImmediately;
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
+(EZMicrophone*)microphoneWithDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription
startsImmediately:(BOOL)startsImmediately;
#pragma mark - Singleton
///-----------------------------------------------------------
/// @name Shared Instance
@@ -199,4 +228,16 @@
*/
-(AudioStreamBasicDescription)audioStreamBasicDescription;
#pragma mark - Setters
///-----------------------------------------------------------
/// @name Customizing The Microphone Input Format
///-----------------------------------------------------------
/**
Sets the AudioStreamBasicDescription on the microphone input.
@warning Do not set this while fetching audio (startFetchingAudio)
@param asbd The new AudioStreamBasicDescription to use in place of the current audio format description.
*/
-(void)setAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd;
@end
+334 -289
View File
@@ -32,27 +32,45 @@
#import "EZAudio.h"
/// Buses
static const AudioUnitScope kEZAudioMicrophoneInputBus = 1;
static const AudioUnitScope kEZAudioMicrophoneOutputBus = 0;
/// Flags
#if TARGET_OS_IPHONE
static const UInt32 kEZAudioMicrophoneDisableFlag = 1;
#elif TARGET_OS_MAC
static const UInt32 kEZAudioMicrophoneDisableFlag = 0;
#endif
static const UInt32 kEZAudioMicrophoneEnableFlag = 1;
@interface EZMicrophone (){
/// Internal
BOOL _customASBD;
BOOL _isConfigured;
BOOL _isFetching;
/// Stream Description
AEFloatConverter *converter;
AEFloatConverter *converter;
AudioStreamBasicDescription streamFormat;
/// Audio Graph and Input/Output Units
AUGraph graph;
AudioUnit microphoneInput;
AudioUnit outputUnit;
/// Audio Buffers
float **floatBuffers;
AudioBufferList *microphoneInputBuffer;
/// Sample Time Offsets
Float64 firstInputSampleTime;
Float64 inToOutSampleTimeOffset;
/// Device Parameters
Float64 _deviceSampleRate;
Float32 _deviceBufferDuration;
UInt32 _deviceBufferFrameSize;
#if TARGET_OS_IPHONE
#elif TARGET_OS_MAC
Float64 inputScopeSampleRate;
#endif
}
@end
@@ -67,26 +85,15 @@ static OSStatus inputCallback(void *inRefCon,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData ) {
EZMicrophone *microphone = (__bridge EZMicrophone*)inRefCon;
OSStatus result = noErr;
#if TARGET_OS_IPHONE
// Render audio into buffer
result = AudioUnitRender(microphone->microphoneInput,
ioActionFlags,
inTimeStamp,
1,
inNumberFrames,
microphone->microphoneInputBuffer);
#elif TARGET_OS_MAC
// Retrive the captured samples from the input
result = AudioUnitRender(microphone->microphoneInput,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
microphone->microphoneInputBuffer);
#endif
if( !result ){
// Notify delegate (OF-style)
@autoreleasepool {
@@ -139,13 +146,31 @@ static OSStatus inputCallback(void *inRefCon,
return self;
}
-(EZMicrophone *)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription {
self = [self initWithMicrophoneDelegate:microphoneDelegate];
if(self){
_customASBD = YES;
streamFormat = audioStreamBasicDescription;
}
return self;
}
-(EZMicrophone *)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
startsImmediately:(BOOL)startsImmediately {
self = [self initWithMicrophoneDelegate:microphoneDelegate];
if(self){
if(startsImmediately){
[self startFetchingAudio];
}
startsImmediately ? [self startFetchingAudio] : -1;
}
return self;
}
-(EZMicrophone *)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription
startsImmediately:(BOOL)startsImmediately {
self = [self initWithMicrophoneDelegate:microphoneDelegate withAudioStreamBasicDescription:audioStreamBasicDescription];
if(self){
startsImmediately ? [self startFetchingAudio] : -1;
}
return self;
}
@@ -155,12 +180,26 @@ static OSStatus inputCallback(void *inRefCon,
return [[EZMicrophone alloc] initWithMicrophoneDelegate:microphoneDelegate];
}
+(EZMicrophone *)microphoneWithDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription {
return [[EZMicrophone alloc] initWithMicrophoneDelegate:microphoneDelegate
withAudioStreamBasicDescription:audioStreamBasicDescription];
}
+(EZMicrophone *)microphoneWithDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
startsImmediately:(BOOL)startsImmediately {
return [[EZMicrophone alloc] initWithMicrophoneDelegate:microphoneDelegate
startsImmediately:startsImmediately];
}
+(EZMicrophone *)microphoneWithDelegate:(id<EZMicrophoneDelegate>)microphoneDelegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription
startsImmediately:(BOOL)startsImmediately {
return [[EZMicrophone alloc] initWithMicrophoneDelegate:microphoneDelegate
withAudioStreamBasicDescription:audioStreamBasicDescription
startsImmediately:startsImmediately];
}
#pragma mark - Singleton
+(EZMicrophone*)sharedMicrophone {
static EZMicrophone *_sharedMicrophone = nil;
@@ -216,218 +255,142 @@ static OSStatus inputCallback(void *inRefCon,
}
}
#if TARGET_OS_IPHONE
-(void)setAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd {
if( self.microphoneOn ){
NSAssert(self.microphoneOn,@"Cannot set the AudioStreamBasicDescription while microphone is fetching audio");
}
else {
_customASBD = YES;
streamFormat = asbd;
[self _configureStreamFormatWithSampleRate:_deviceSampleRate];
}
}
#pragma mark - Configure The Input Unit
-(void)_createInputUnit {
// Create localized copy of self
EZMicrophone *microphone = (EZMicrophone*)self;
// Get component description for input
AudioComponentDescription inputComponentDescription = [self _getInputAudioComponentDescription];
AudioComponentDescription inputComponentDescription = {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_RemoteIO,
.componentManufacturer = kAudioUnitManufacturer_Apple,
.componentFlags = 0,
.componentFlagsMask = 0
};
// Try and find the component
AudioComponent inputComponent = AudioComponentFindNext( NULL , &inputComponentDescription );
if( inputComponent == NULL ){
NSLog(@"Couldn't get input component unit!");
return;
}
// Get the input component
AudioComponent inputComponent = [self _getInputComponentWithAudioComponentDescription:inputComponentDescription];
// Create a new instance of the component and store it for internal use
[EZAudio checkResult:AudioComponentInstanceNew(inputComponent,
&microphone->microphoneInput)
operation:"Couldn't open component for microphone input unit."];
[self _createNewInstanceForInputComponent:inputComponent];
// Enable I/O on microphone input unit
UInt32 disableFlag = 1; UInt32 enableFlag = 1;
AudioUnitScope outputBus = 0; AudioUnitScope inputBus = 1;
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
inputBus,
&enableFlag,
sizeof(enableFlag))
operation:"Couldn't enable input on the remote i/o unit"];
// Enable Input Scope
[self _enableInputScope];
// Could set the output if we wanted to play out the mic's buffer
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
outputBus,
&disableFlag,
sizeof(disableFlag))
operation:"Couldn't enable input on the remote i/o unit"];
// Disable Output Scope
[self _disableOutputScope];
// Get the hardware sample rate
Float64 hardwareSampleRate = 44100;
#if !(TARGET_IPHONE_SIMULATOR)
UInt32 propSize = sizeof(hardwareSampleRate);
[EZAudio checkResult:AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate,
&propSize,
&hardwareSampleRate)
operation:"Could not get hardware sample rate"];
#endif
// Get the default device if we need to (OSX only, iOS uses RemoteIO)
#if TARGET_OS_IPHONE
// Do nothing (using RemoteIO)
#elif TARGET_OS_MAC
[self _configureDefaultDevice];
#endif
// Set the stream format
microphone->streamFormat.mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);
microphone->streamFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
microphone->streamFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
microphone->streamFormat.mChannelsPerFrame = 2;
microphone->streamFormat.mFormatFlags = kAudioFormatFlagsCanonical | kAudioFormatFlagIsNonInterleaved;
microphone->streamFormat.mFormatID = kAudioFormatLinearPCM;
microphone->streamFormat.mFramesPerPacket = 1;
microphone->streamFormat.mSampleRate = hardwareSampleRate;
// Configure device and pull hardware specific sampling rate (default = 44.1 kHz)
_deviceSampleRate = [self _configureDeviceSampleRateWithDefault:44100.0];
// Get the buffer duration (approximate for simulator, real device will have it's preferred value set)
Float32 bufferDuration = 0.0232;
UInt32 propertySize = sizeof(bufferDuration);
#if !(TARGET_IPHONE_SIMULATOR)
[EZAudio checkResult:AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration,
sizeof(propertySize),
&bufferDuration)
operation:"Couldn't set the preferred buffer duration"];
// Get the preferred buffer size
[EZAudio checkResult:AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration,
&propertySize,
&bufferDuration)
operation:"Could not get preferred buffer size"];
#endif
// Configure device and pull hardware specific buffer duration (default = 0.0232)
_deviceBufferDuration = [self _configureDeviceBufferDurationWithDefault:0.0232];
// Configure the stream format with the hardware sample rate
[self _configureStreamFormatWithSampleRate:_deviceSampleRate];
// Notify delegate the audio stream basic description was successfully created
[self _notifyDelegateOfStreamFormat];
// Get buffer frame size
_deviceBufferFrameSize = [self _getBufferFrameSize];
// Create the audio buffer list and pre-malloc the buffers in the list
propertySize = offsetof( AudioBufferList, mBuffers[0] ) + ( sizeof( AudioBuffer ) * microphone->streamFormat.mChannelsPerFrame );
microphone->microphoneInputBuffer = (AudioBufferList*)malloc(propertySize);
[self _configureAudioBufferListWithFrameSize:_deviceBufferFrameSize];
// Get the maximum number of frames
UInt32 bufferSizeFrames;
propertySize = sizeof(UInt32);
[EZAudio checkResult:AudioUnitGetProperty(microphone->microphoneInput,
kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global,
outputBus,
&bufferSizeFrames,
&propertySize)
operation:"Failed to get maximum number of frames"];
microphone->microphoneInputBuffer->mNumberBuffers = microphone->streamFormat.mChannelsPerFrame;
UInt32 bufferSizeBytes = bufferSizeFrames * microphone->streamFormat.mBytesPerFrame;
for( UInt32 i = 0; i < microphone->microphoneInputBuffer->mNumberBuffers; i++ ){
microphone->microphoneInputBuffer->mBuffers[i].mNumberChannels = 1;
microphone->microphoneInputBuffer->mBuffers[i].mDataByteSize = bufferSizeBytes;
microphone->microphoneInputBuffer->mBuffers[i].mData = malloc(bufferSizeBytes);
}
// Setup the converter, but do a lazy set for the float buffer
microphone->converter = [[AEFloatConverter alloc] initWithSourceFormat:microphone->streamFormat];
microphone->floatBuffers = (float**)malloc(sizeof(float*)*microphone->streamFormat.mChannelsPerFrame);
for ( int i=0; i<microphone->streamFormat.mChannelsPerFrame; i++ ) {
microphone->floatBuffers[i] = (float*)malloc(bufferSizeBytes);
assert(microphone->floatBuffers[i]);
}
// Set the stream format for output on the microphone's input scope
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
outputBus,
&microphone->streamFormat,
sizeof(microphone->streamFormat))
operation:"Could not set microphone's stream format bus 0"];
// Set the stream format for the input on the microphone's output scope
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
inputBus,
&microphone->streamFormat,
sizeof(microphone->streamFormat))
operation:"Could not set microphone's stream format bus 1"];
// Notify delegate the audio stream basic description was successfully created
if( microphone.microphoneDelegate ){
if( [microphone.microphoneDelegate respondsToSelector:@selector(microphone:hasAudioStreamBasicDescription:) ] ){
[microphone.microphoneDelegate microphone:microphone
hasAudioStreamBasicDescription:microphone->streamFormat];
}
}
// Set the float converter's stream format
[self _configureFloatConverterWithFrameSize:_deviceBufferFrameSize];
// Setup input callback
AURenderCallbackStruct microphoneCallbackStruct;
microphoneCallbackStruct.inputProc = inputCallback;
microphoneCallbackStruct.inputProcRefCon = (__bridge void *)microphone;
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
inputBus,
&microphoneCallbackStruct,
sizeof(microphoneCallbackStruct))
operation:"Couldn't set input callback"];
[self _configureInputCallback];
// Disable buffer allocation for the recorder (optional - do this if we want to pass in our own)
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
kAudioUnitProperty_ShouldAllocateBuffer,
kAudioUnitScope_Output,
inputBus,
&disableFlag,
sizeof(disableFlag))
operation:"Could not disable audio unit allocating its own buffers"];
// Disable buffer allocation (optional - do this if we want to pass in our own)
[self _disableCallbackBufferAllocation];
// Initialize the audio unit
[EZAudio checkResult:AudioUnitInitialize( microphone->microphoneInput )
[EZAudio checkResult:AudioUnitInitialize( microphoneInput )
operation:"Couldn't initialize the input unit"];
}
#elif TARGET_OS_MAC
-(void)_createInputUnit {
#pragma mark - Audio Component Initialization
-(AudioComponentDescription)_getInputAudioComponentDescription {
// Create localized copy of self
EZMicrophone *microphone = (EZMicrophone*)self;
// Create component description for input HAL
AudioComponentDescription inputComponentDescription = {0};
// Create an input component description for mic input
AudioComponentDescription inputComponentDescription;
inputComponentDescription.componentType = kAudioUnitType_Output;
inputComponentDescription.componentSubType = kAudioUnitSubType_HALOutput;
inputComponentDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
inputComponentDescription.componentFlags = 0;
inputComponentDescription.componentFlagsMask = 0;
#if TARGET_OS_IPHONE
inputComponentDescription.componentSubType = kAudioUnitSubType_RemoteIO;
#elif TARGET_OS_MAC
inputComponentDescription.componentSubType = kAudioUnitSubType_HALOutput;
#endif
// Return the successfully created input component description
return inputComponentDescription;
}
-(AudioComponent)_getInputComponentWithAudioComponentDescription:(AudioComponentDescription)audioComponentDescription {
// Try and find the component
AudioComponent inputComponent = AudioComponentFindNext( NULL , &inputComponentDescription );
if( inputComponent == NULL ){
NSLog(@"Couldn't get input component unit!");
return;
}
AudioComponent inputComponent = AudioComponentFindNext( NULL , &audioComponentDescription );
NSAssert(inputComponent,@"Couldn't get input component unit!");
return inputComponent;
// Create a new instance of the component and store it for internal use
[EZAudio checkResult:AudioComponentInstanceNew(inputComponent,
&microphone->microphoneInput )
}
-(void)_createNewInstanceForInputComponent:(AudioComponent)audioComponent {
[EZAudio checkResult:AudioComponentInstanceNew(audioComponent,
&microphoneInput )
operation:"Couldn't open component for microphone input unit."];
// Enable I/O on microphone input unit
UInt32 disableFlag = 0; UInt32 enableFlag = 1;
AudioUnitScope outputBus = 0; AudioUnitScope inputBus = 1;
// Input Scope
[EZAudio checkResult:AudioUnitSetProperty( microphone->microphoneInput,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
inputBus,
&enableFlag,
sizeof(enableFlag))
operation:"Couldn't enable input on I/O unit."];
// Output Scope
[EZAudio checkResult:AudioUnitSetProperty( microphone->microphoneInput,
}
#pragma mark - Input/Output Scope Initialization
-(void)_disableOutputScope {
[EZAudio checkResult:AudioUnitSetProperty(microphoneInput,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
outputBus,
&disableFlag,
sizeof(enableFlag))
kEZAudioMicrophoneOutputBus,
&kEZAudioMicrophoneDisableFlag,
sizeof(kEZAudioMicrophoneDisableFlag))
operation:"Couldn't disable output on I/O unit."];
}
-(void)_enableInputScope {
[EZAudio checkResult:AudioUnitSetProperty(microphoneInput,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
kEZAudioMicrophoneInputBus,
&kEZAudioMicrophoneEnableFlag,
sizeof(kEZAudioMicrophoneEnableFlag))
operation:"Couldn't enable input on I/O unit."];
}
#pragma mark - Pull Default Device (OSX)
#if TARGET_OS_IPHONE
// Not needed, using RemoteIO
#elif TARGET_OS_MAC
-(void)_configureDefaultDevice {
// Get the default audio input device (pulls an abstract type from system preferences)
AudioDeviceID defaultDevice = kAudioObjectUnknown;
UInt32 propertySize = sizeof(defaultDevice);
AudioDeviceID defaultDevice = kAudioObjectUnknown;
UInt32 propSize = sizeof(defaultDevice);
AudioObjectPropertyAddress defaultDeviceProperty;
defaultDeviceProperty.mSelector = kAudioHardwarePropertyDefaultInputDevice;
defaultDeviceProperty.mScope = kAudioObjectPropertyScopeGlobal;
@@ -436,117 +399,199 @@ static OSStatus inputCallback(void *inRefCon,
&defaultDeviceProperty,
0,
NULL,
&propertySize,
&propSize,
&defaultDevice)
operation:"Couldn't get default input device"];
// Set the default device on the microphone input unit
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
propSize = sizeof(defaultDevice);
[EZAudio checkResult:AudioUnitSetProperty(microphoneInput,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
outputBus,
kEZAudioMicrophoneOutputBus,
&defaultDevice,
sizeof(defaultDevice))
propSize)
operation:"Couldn't set default device on I/O unit"];
// Get the stream format description from the newly created input unit and assign it to the output of the input unit
propertySize = sizeof(AudioStreamBasicDescription);
[EZAudio checkResult:AudioUnitGetProperty( microphone->microphoneInput,
AudioStreamBasicDescription inputScopeFormat;
propSize = sizeof(AudioStreamBasicDescription);
[EZAudio checkResult:AudioUnitGetProperty(microphoneInput,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
inputBus,
&microphone->streamFormat,
&propertySize)
kEZAudioMicrophoneInputBus,
&inputScopeFormat,
&propSize)
operation:"Couldn't get ASBD from input unit (1)"];
// Assign the same stream format description from the output of the input unit and pull the sample rate
AudioStreamBasicDescription deviceFormat;
[EZAudio checkResult:AudioUnitGetProperty( microphone->microphoneInput,
AudioStreamBasicDescription outputScopeFormat;
propSize = sizeof(AudioStreamBasicDescription);
[EZAudio checkResult:AudioUnitGetProperty(microphoneInput,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
inputBus,
&deviceFormat,
&propertySize)
kEZAudioMicrophoneInputBus,
&outputScopeFormat,
&propSize)
operation:"Couldn't get ASBD from input unit (2)"];
microphone->streamFormat.mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);
microphone->streamFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
microphone->streamFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
microphone->streamFormat.mChannelsPerFrame = 2;
microphone->streamFormat.mFormatFlags = kAudioFormatFlagsCanonical | kAudioFormatFlagIsNonInterleaved;
microphone->streamFormat.mFormatID = kAudioFormatLinearPCM;
microphone->streamFormat.mFramesPerPacket = 1;
microphone->streamFormat.mSampleRate = deviceFormat.mSampleRate;
// Readjust property size for ASBD and set the value on the input unit
propertySize = sizeof(AudioStreamBasicDescription);
[EZAudio checkResult:AudioUnitSetProperty(microphone->microphoneInput,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
inputBus,
&microphone->streamFormat,
propertySize)
operation:"Couldn't set ASBD on input unit"];
// Notify delegate the audio stream basic description was successfully created
if( microphone.microphoneDelegate ){
if( [microphone.microphoneDelegate respondsToSelector:@selector(microphone:hasAudioStreamBasicDescription:) ] ){
[microphone.microphoneDelegate microphone:microphone
hasAudioStreamBasicDescription:microphone->streamFormat];
}
}
// Setup the audio buffers to capture the input audio
UInt32 bufferSizeFrames = 0;
propertySize = sizeof(UInt32);
[EZAudio checkResult:AudioUnitGetProperty(microphone->microphoneInput,
kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global,
outputBus,
&bufferSizeFrames,
&propertySize)
operation:"Could not get buffer frame size from input unit"];
UInt32 bufferSizeBytes = bufferSizeFrames * sizeof(Float32);
// Create the audio buffer list and pre-malloc the buffers in the list
propertySize = offsetof( AudioBufferList, mBuffers[0] ) + ( sizeof( AudioBuffer ) * microphone->streamFormat.mChannelsPerFrame );
microphone->microphoneInputBuffer = (AudioBufferList*)malloc(propertySize);
microphone->microphoneInputBuffer->mNumberBuffers = microphone->streamFormat.mChannelsPerFrame;
for( UInt32 i = 0; i < microphone->microphoneInputBuffer->mNumberBuffers; i++ ){
microphone->microphoneInputBuffer->mBuffers[i].mNumberChannels = 1;
microphone->microphoneInputBuffer->mBuffers[i].mDataByteSize = bufferSizeBytes;
microphone->microphoneInputBuffer->mBuffers[i].mData = malloc(bufferSizeBytes);
}
// Set the convert's stream format
microphone->converter = [[AEFloatConverter alloc] initWithSourceFormat:microphone->streamFormat];
microphone->floatBuffers = (float**)malloc(sizeof(float*)*microphone->streamFormat.mChannelsPerFrame);
assert(microphone->floatBuffers);
for ( int i=0; i<microphone->streamFormat.mChannelsPerFrame; i++ ) {
microphone->floatBuffers[i] = (float*)malloc(bufferSizeBytes);
assert(microphone->floatBuffers[i]);
}
// Setup input callback
AURenderCallbackStruct microphoneCallbackStruct;
microphoneCallbackStruct.inputProc = inputCallback;
microphoneCallbackStruct.inputProcRefCon = (__bridge void *)microphone;
[EZAudio checkResult:AudioUnitSetProperty( microphone->microphoneInput,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
0,
&microphoneCallbackStruct,
sizeof(microphoneCallbackStruct))
operation:"Couldn't set input callback"];
// Initialize the audio unit
[EZAudio checkResult:AudioUnitInitialize( microphone->microphoneInput )
operation:"Couldn't initialize the input unit"];
microphone->firstInputSampleTime = -1;
microphone->inToOutSampleTimeOffset = -1;
// Store the input scope's sample rate
inputScopeSampleRate = inputScopeFormat.mSampleRate;
}
#endif
#pragma mark - Pull Sample Rate
-(Float64)_configureDeviceSampleRateWithDefault:(float)defaultSampleRate {
Float64 hardwareSampleRate = defaultSampleRate;
#if TARGET_OS_IPHONE
// Use approximations for simulator and pull from real device if connected
#if !(TARGET_IPHONE_SIMULATOR)
// Sample Rate
UInt32 propSize = sizeof(Float64);
[EZAudio checkResult:AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate,
&propSize,
&hardwareSampleRate)
operation:"Could not get hardware sample rate from device"];
#endif
#elif TARGET_OS_MAC
hardwareSampleRate = inputScopeSampleRate;
#endif
return hardwareSampleRate;
}
#pragma mark - Pull Buffer Duration
-(Float32)_configureDeviceBufferDurationWithDefault:(float)defaultBufferDuration {
Float32 bufferDuration = defaultBufferDuration; // Type 1/43 by default
#if TARGET_OS_IPHONE
// Use approximations for simulator and pull from real device if connected
#if !(TARGET_IPHONE_SIMULATOR)
UInt32 propSize = sizeof(Float32);
[EZAudio checkResult:AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration,
propSize,
&bufferDuration)
operation:"Couldn't set the preferred buffer duration from device"];
// Buffer Size
propSize = sizeof(bufferDuration);
[EZAudio checkResult:AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration,
&propSize,
&bufferDuration)
operation:"Could not get preferred buffer size from device"];
#endif
#elif TARGET_OS_MAC
#endif
return bufferDuration;
}
#pragma mark - Pull Buffer Frame Size
-(UInt32)_getBufferFrameSize {
UInt32 bufferFrameSize;
UInt32 propSize = sizeof(bufferFrameSize);
[EZAudio checkResult:AudioUnitGetProperty(microphoneInput,
#if TARGET_OS_IPHONE
kAudioUnitProperty_MaximumFramesPerSlice,
#elif TARGET_OS_MAC
kAudioDevicePropertyBufferFrameSize,
#endif
kAudioUnitScope_Global,
kEZAudioMicrophoneOutputBus,
&bufferFrameSize,
&propSize)
operation:"Failed to get buffer frame size"];
return bufferFrameSize;
}
#pragma mark - Stream Format Initialization
-(void)_configureStreamFormatWithSampleRate:(Float64)sampleRate {
// Set the stream format
if( !_customASBD ){
streamFormat = [EZAudio stereoCanonicalNonInterleavedFormatWithSampleRate:sampleRate];
}
else {
streamFormat.mSampleRate = sampleRate;
}
UInt32 propSize = sizeof(streamFormat);
// Set the stream format for output on the microphone's input scope
[EZAudio checkResult:AudioUnitSetProperty(microphoneInput,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kEZAudioMicrophoneOutputBus,
&streamFormat,
propSize)
operation:"Could not set microphone's stream format bus 0"];
// Set the stream format for the input on the microphone's output scope
[EZAudio checkResult:AudioUnitSetProperty(microphoneInput,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
kEZAudioMicrophoneInputBus,
&streamFormat,
propSize)
operation:"Could not set microphone's stream format bus 1"];
}
-(void)_notifyDelegateOfStreamFormat {
if( _microphoneDelegate ){
if( [_microphoneDelegate respondsToSelector:@selector(microphone:hasAudioStreamBasicDescription:) ] ){
[_microphoneDelegate microphone:self
hasAudioStreamBasicDescription:streamFormat];
}
}
}
#pragma mark - AudioBufferList Initialization
-(void)_configureAudioBufferListWithFrameSize:(UInt32)bufferFrameSize {
UInt32 bufferSizeBytes = bufferFrameSize * streamFormat.mBytesPerFrame;
UInt32 propSize = offsetof( AudioBufferList, mBuffers[0] ) + ( sizeof( AudioBuffer ) *streamFormat.mChannelsPerFrame );
microphoneInputBuffer = (AudioBufferList*)malloc(propSize);
microphoneInputBuffer->mNumberBuffers = streamFormat.mChannelsPerFrame;
for( UInt32 i = 0; i < microphoneInputBuffer->mNumberBuffers; i++ ){
microphoneInputBuffer->mBuffers[i].mNumberChannels = 1;
microphoneInputBuffer->mBuffers[i].mDataByteSize = bufferSizeBytes;
microphoneInputBuffer->mBuffers[i].mData = malloc(bufferSizeBytes);
}
}
#pragma mark - Float Converter Initialization
-(void)_configureFloatConverterWithFrameSize:(UInt32)bufferFrameSize {
UInt32 bufferSizeBytes = bufferFrameSize * streamFormat.mBytesPerFrame;
converter = [[AEFloatConverter alloc] initWithSourceFormat:streamFormat];
floatBuffers = (float**)malloc(sizeof(float*)*streamFormat.mChannelsPerFrame);
assert(floatBuffers);
for ( int i=0; i<streamFormat.mChannelsPerFrame; i++ ) {
floatBuffers[i] = (float*)malloc(bufferSizeBytes);
assert(floatBuffers[i]);
}
}
#pragma mark - Input Callback Initialization
-(void)_configureInputCallback {
AURenderCallbackStruct microphoneCallbackStruct;
microphoneCallbackStruct.inputProc = inputCallback;
microphoneCallbackStruct.inputProcRefCon = (__bridge void *)self;
[EZAudio checkResult:AudioUnitSetProperty(microphoneInput,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
// output bus for mac
#if TARGET_OS_IPHONE
kEZAudioMicrophoneInputBus,
#elif TARGET_OS_MAC
kEZAudioMicrophoneOutputBus,
#endif
&microphoneCallbackStruct,
sizeof(microphoneCallbackStruct))
operation:"Couldn't set input callback"];
}
-(void)_disableCallbackBufferAllocation {
[EZAudio checkResult:AudioUnitSetProperty(microphoneInput,
kAudioUnitProperty_ShouldAllocateBuffer,
kAudioUnitScope_Output,
kEZAudioMicrophoneInputBus,
&kEZAudioMicrophoneDisableFlag,
sizeof(kEZAudioMicrophoneDisableFlag))
operation:"Could not disable audio unit allocating its own buffers"];
}
@end
+32
View File
@@ -106,6 +106,16 @@ inNumberFrames:(UInt32)inNumberFrames
*/
-(id)initWithDataSource:(id<EZOutputDataSource>)dataSource;
/**
Creates a new instance of the EZOutput and allows the caller to specify an EZOutputDataSource.
@param dataSource The EZOutputDataSource that will be used to pull the audio data for the output callback.
@param audioStreamBasicDescription The AudioStreamBasicDescription of the EZOutput.
@warning AudioStreamBasicDescriptions that are invalid will cause the EZOutput to fail to initialize
@return A newly created instance of the EZOutput class.
*/
-(id) initWithDataSource:(id<EZOutputDataSource>)dataSource
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription;
#pragma mark - Class Initializers
///-----------------------------------------------------------
/// @name Class Initializers
@@ -118,6 +128,16 @@ inNumberFrames:(UInt32)inNumberFrames
*/
+(EZOutput*)outputWithDataSource:(id<EZOutputDataSource>)dataSource;
/**
Class method to create a new instance of the EZOutput and allows the caller to specify an EZOutputDataSource.
@param dataSource The EZOutputDataSource that will be used to pull the audio data for the output callback.
@param audioStreamBasicDescription The AudioStreamBasicDescription of the EZOutput.
@warning AudioStreamBasicDescriptions that are invalid will cause the EZOutput to fail to initialize
@return A newly created instance of the EZOutput class.
*/
+(EZOutput*)outputWithDataSource:(id<EZOutputDataSource>)dataSource
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription;
#pragma mark - Singleton
///-----------------------------------------------------------
/// @name Shared Instance
@@ -155,4 +175,16 @@ inNumberFrames:(UInt32)inNumberFrames
*/
-(BOOL)isPlaying;
#pragma mark - Setters
///-----------------------------------------------------------
/// @name Customizing The Output Format
///-----------------------------------------------------------
/**
Sets the AudioStreamBasicDescription on the output.
@warning Do not set this during playback.
@param asbd The new AudioStreamBasicDescription to use in place of the current audio format description.
*/
-(void)setAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd;
@end
+130 -42
View File
@@ -27,9 +27,18 @@
#import "EZAudio.h"
/// Buses
static const AudioUnitScope kEZAudioMicrophoneOutputBus = 0;
/// Flags
static const UInt32 kEZAudioMicrophoneEnableFlag = 1;
static const UInt32 kEZAudioMicrophoneDisableFlag = 0;
@interface EZOutput (){
BOOL _isPlaying;
AudioUnit _outputUnit;
BOOL _customASBD;
BOOL _isPlaying;
AudioStreamBasicDescription _outputASBD;
AudioUnit _outputUnit;
}
@end
@@ -57,8 +66,8 @@ static OSStatus OutputRenderCallback(void *inRefCon,
TPCircularBuffer *circularBuffer = [output.outputDataSource outputShouldUseCircularBuffer:output];
if( !circularBuffer ){
Float32 *left = (Float32*)ioData->mBuffers[0].mData;
Float32 *right = (Float32*)ioData->mBuffers[1].mData;
AudioUnitSampleType *left = (AudioUnitSampleType*)ioData->mBuffers[0].mData;
AudioUnitSampleType *right = (AudioUnitSampleType*)ioData->mBuffers[1].mData;
for(int i = 0; i < inNumberFrames; i++ ){
left[ i ] = 0.0f;
right[ i ] = 0.0f;
@@ -72,7 +81,8 @@ static OSStatus OutputRenderCallback(void *inRefCon,
// Get the desired amount of bytes to copy
int32_t bytesToCopy = ioData->mBuffers[0].mDataByteSize;
AudioSampleType *targetBuffer = (AudioSampleType*)ioData->mBuffers[0].mData;
AudioSampleType *left = (AudioSampleType*)ioData->mBuffers[0].mData;
AudioSampleType *right = (AudioSampleType*)ioData->mBuffers[1].mData;
// Get the available bytes in the circular buffer
int32_t availableBytes;
@@ -80,7 +90,8 @@ static OSStatus OutputRenderCallback(void *inRefCon,
// Ideally we'd have all the bytes to be copied, but compare it against the available bytes (get min)
int32_t amount = MIN(bytesToCopy,availableBytes);
memcpy(targetBuffer,buffer,amount);
memcpy(left,buffer,amount);
memcpy(right,buffer,amount);
// Consume those bytes ( this will internally push the head of the circular buffer )
TPCircularBufferConsume(circularBuffer,amount);
@@ -93,28 +104,21 @@ static OSStatus OutputRenderCallback(void *inRefCon,
needsBufferListWithFrames:inNumberFrames
withBufferSize:&bufferSize];
if( !bufferList ){
Float32 *left = (Float32*)ioData->mBuffers[0].mData;
Float32 *right = (Float32*)ioData->mBuffers[1].mData;
for(int i = 0; i < inNumberFrames; i++ ){
left[ i ] = 0.0f;
right[ i ] = 0.0f;
}
return noErr;
};
// Interleaved
if( !(ioData->mNumberBuffers == 1) ){
Float32 *left = (Float32*)ioData->mBuffers[0].mData;
Float32 *right = (Float32*)ioData->mBuffers[1].mData;
AudioUnitSampleType *left = (AudioUnitSampleType*)ioData->mBuffers[0].mData;
AudioUnitSampleType *right = (AudioUnitSampleType*)ioData->mBuffers[1].mData;
AudioUnitSampleType *interleaved = (AudioUnitSampleType*)bufferList->mBuffers[0].mData;
for(int i = 0; i < inNumberFrames; i++ ){
if( bufferList ){
Float32 *interleaved = (Float32*)bufferList->mBuffers[0].mData;
left[i] = interleaved[i];
right[i] = interleaved[i];
*left++ = *interleaved++;
*right++ = *interleaved++;
}
else {
left[ i ] = 0.0f;
right[ i ] = 0.0f;
*left++ = 0.0f;
*right++ = 0.0f;
}
}
}
@@ -152,11 +156,28 @@ static OSStatus OutputRenderCallback(void *inRefCon,
return self;
}
-(id) initWithDataSource:(id<EZOutputDataSource>)dataSource
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription {
self = [super init];
if(self){
_customASBD = YES;
_outputASBD = audioStreamBasicDescription;
self.outputDataSource = dataSource;
[self _configureOutput];
}
return self;
}
#pragma mark - Class Initializers
+(EZOutput*)outputWithDataSource:(id<EZOutputDataSource>)dataSource {
return [[EZOutput alloc] initWithDataSource:dataSource];
}
+(EZOutput *)outputWithDataSource:(id<EZOutputDataSource>)dataSource
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription {
return [[EZOutput alloc] initWithDataSource:dataSource withAudioStreamBasicDescription:audioStreamBasicDescription];
}
#pragma mark - Singleton
+(EZOutput*)sharedOutput {
static EZOutput *_sharedOutput = nil;
@@ -167,18 +188,60 @@ static OSStatus OutputRenderCallback(void *inRefCon,
return _sharedOutput;
}
#pragma mark - Private Configuration
#pragma mark - Audio Component Initialization
-(AudioComponentDescription)_getOutputAudioComponentDescription {
// Create an output component description for default output device
AudioComponentDescription outputComponentDescription;
outputComponentDescription.componentFlags = 0;
outputComponentDescription.componentFlagsMask = 0;
outputComponentDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
#if TARGET_OS_IPHONE
outputComponentDescription.componentSubType = kAudioUnitSubType_RemoteIO;
#elif TARGET_OS_MAC
outputComponentDescription.componentSubType = kAudioUnitSubType_DefaultOutput;
#endif
outputComponentDescription.componentType = kAudioUnitType_Output;
return outputComponentDescription;
}
-(AudioComponent)_getOutputComponentWithAudioComponentDescription:(AudioComponentDescription)outputComponentDescription {
// Try and find the component
AudioComponent outputComponent = AudioComponentFindNext( NULL , &outputComponentDescription );
NSAssert(outputComponent,@"Couldn't get input component unit!");
return outputComponent;
}
-(void)_createNewInstanceForOutputComponent:(AudioComponent)outputComponent {
//
[EZAudio checkResult:AudioComponentInstanceNew( outputComponent, &_outputUnit )
operation:"Failed to open component for output unit"];
}
#pragma mark - Configure The Output Unit
//-(void)_configureOutput {
//
// // Get component description for output
// AudioComponentDescription outputComponentDescription = [self _getOutputAudioComponentDescription];
//
// // Get the output component
// AudioComponent outputComponent = [self _getOutputComponentWithAudioComponentDescription:outputComponentDescription];
//
// // Create a new instance of the component and store it for internal use
// [self _createNewInstanceForOutputComponent:outputComponent];
//
//}
#if TARGET_OS_IPHONE
-(void)_configureOutput {
//
AudioComponentDescription outputcd;
outputcd.componentFlags = 0;
outputcd.componentFlagsMask = 0;
outputcd.componentFlags = 0;
outputcd.componentFlagsMask = 0;
outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
outputcd.componentSubType = kAudioUnitSubType_RemoteIO;
outputcd.componentType = kAudioUnitType_Output;
outputcd.componentSubType = kAudioUnitSubType_RemoteIO;
outputcd.componentType = kAudioUnitType_Output;
//
AudioComponent comp = AudioComponentFindNext(NULL,&outputcd);
@@ -186,8 +249,8 @@ static OSStatus OutputRenderCallback(void *inRefCon,
operation:"Failed to get output unit"];
// Setup the output unit for playback
UInt32 oneFlag = 1;
AudioUnitElement bus0 = 0;
UInt32 oneFlag = 1;
AudioUnitElement bus0 = 0;
[EZAudio checkResult:AudioUnitSetProperty(_outputUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
@@ -206,25 +269,18 @@ static OSStatus OutputRenderCallback(void *inRefCon,
operation:"Could not get hardware sample rate"];
#endif
// Setup an ASBD in canonical format
AudioStreamBasicDescription asbd;
memset(&asbd, 0, sizeof(asbd));
asbd.mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);
asbd.mBytesPerFrame = sizeof(AudioUnitSampleType);
asbd.mBytesPerPacket = sizeof(AudioUnitSampleType);
asbd.mChannelsPerFrame = 2;
asbd.mFormatFlags = kAudioFormatFlagsCanonical | kAudioFormatFlagIsNonInterleaved;
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFramesPerPacket = 1;
asbd.mSampleRate = hardwareSampleRate;
// Setup an ASBD in canonical format by default
if( !_customASBD ){
_outputASBD = [EZAudio stereoCanonicalNonInterleavedFormatWithSampleRate:hardwareSampleRate];
}
// Set the format for output
[EZAudio checkResult:AudioUnitSetProperty(_outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
bus0,
&asbd,
sizeof(asbd))
&_outputASBD,
sizeof(_outputASBD))
operation:"Couldn't set the ASBD for input scope/bos 0"];
//
@@ -262,9 +318,22 @@ static OSStatus OutputRenderCallback(void *inRefCon,
}
[EZAudio checkResult:AudioComponentInstanceNew(comp,&_outputUnit)
operation:"Failed to open component for output unit"];
// Setup an ASBD in canonical format by default
if( !_customASBD ){
_outputASBD = [EZAudio stereoCanonicalNonInterleavedFormatWithSampleRate:44100];
}
// Set the format for output
[EZAudio checkResult:AudioUnitSetProperty(_outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&_outputASBD,
sizeof(_outputASBD))
operation:"Couldn't set the ASBD for input scope/bos 0"];
//
AURenderCallbackStruct input;
input.inputProc = OutputRenderCallback;
@@ -306,6 +375,25 @@ static OSStatus OutputRenderCallback(void *inRefCon,
return _isPlaying;
}
#pragma mark - Setters
-(void)setAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd {
if( self.isPlaying ){
NSAssert(self.isPlaying,@"Cannot set the AudioStreamBasicDescription while output is performing playback");
}
else {
_customASBD = YES;
_outputASBD = asbd;
// Set the format for output
[EZAudio checkResult:AudioUnitSetProperty(_outputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&_outputASBD,
sizeof(_outputASBD))
operation:"Couldn't set the ASBD for input scope/bos 0"];
}
}
-(void)dealloc {
[EZAudio checkResult:AudioOutputUnitStop(_outputUnit)
operation:"Failed to uninitialize output unit"];
+1
View File
@@ -95,6 +95,7 @@ typedef NS_ENUM(NSInteger,EZPlotType){
///-----------------------------------------------------------
/// @name Updating The Plot
///-----------------------------------------------------------
/**
Updates the plot with the new buffer data and tells the view to redraw itself. Caller will provide a float array with the values they expect to see on the y-axis. The plot will internally handle mapping the x-axis and y-axis to the current view port, any interpolation for fills effects, and mirroring.
@param buffer A float array of values to map to the y-axis.
+22 -20
View File
@@ -66,14 +66,7 @@ typedef struct {
#pragma mark - Class Format Helper
+(AudioStreamBasicDescription)defaultDestinationFormat {
AudioStreamBasicDescription destinationFormat;
destinationFormat.mFormatID = kAudioFormatLinearPCM;
destinationFormat.mChannelsPerFrame = 1;
destinationFormat.mBitsPerChannel = 16;
destinationFormat.mBytesPerPacket = destinationFormat.mBytesPerFrame = 2 * destinationFormat.mChannelsPerFrame;
destinationFormat.mFramesPerPacket = 1;
destinationFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; // little-endian
destinationFormat.mSampleRate = 44100.0;
AudioStreamBasicDescription destinationFormat = [EZAudio stereoFloatInterleavedFormatWithSampleRate:44100.0];
return destinationFormat;
}
@@ -82,16 +75,24 @@ typedef struct {
}
#pragma mark - Private Configuation
-(void)_configureRecorderForExistingFile {
}
-(void)_configureRecorderForNewFile {
}
-(void)_configureRecorder {
// Create the extended audio file
[EZAudio checkResult:ExtAudioFileCreateWithURL(_destinationFileURL,
kAudioFileCAFType,
&_destinationFormat,
NULL,
kAudioFileFlags_EraseFile,
&_destinationFile)
operation:"Failed to create ExtendedAudioFile reference"];
kAudioFileCAFType,
&_destinationFormat,
NULL,
kAudioFileFlags_EraseFile,
&_destinationFile)
operation:"Could not open audio file"];
// Set the client format
_clientFormat = _destinationFormat;
@@ -112,7 +113,7 @@ typedef struct {
operation:"Failed to initialize with ExtAudioFileWriteAsync"];
// Setup the audio converter
[EZAudio checkResult:AudioConverterNew(&_sourceFormat, &_clientFormat, &_audioConverter)
[EZAudio checkResult:AudioConverterNew(&_sourceFormat, &_destinationFormat, &_audioConverter)
operation:"Failed to create new audio converter"];
}
@@ -126,18 +127,19 @@ typedef struct {
AudioBufferList *convertedData = [EZAudio audioBufferList];
convertedData->mNumberBuffers = 1;
convertedData->mBuffers[0].mNumberChannels = _clientFormat.mChannelsPerFrame;
convertedData->mBuffers[0].mDataByteSize = outputBufferSize;
convertedData->mBuffers[0].mData = (UInt8*)malloc(sizeof(UInt8)*outputBufferSize);
convertedData->mBuffers[0].mDataByteSize = outputBufferSize*_clientFormat.mChannelsPerFrame;
convertedData->mBuffers[0].mData = (AudioUnitSampleType*)malloc(sizeof(AudioUnitSampleType)*outputBufferSize*_clientFormat.mChannelsPerFrame);
[EZAudio checkResult:AudioConverterFillComplexBuffer(_audioConverter,
complexInputDataProc,
&(EZRecorderConverterStruct){ .sourceBuffer = bufferList },
&bufferSize,
convertedData,
NULL) operation:"Failed while converting buffers"];
NULL)
operation:"Failed while converting buffers"];
// Write the destination audio buffer list into t
[EZAudio checkResult:ExtAudioFileWriteAsync(_destinationFile, bufferSize, convertedData)
[EZAudio checkResult:ExtAudioFileWriteAsync(_destinationFile,bufferSize,convertedData)
operation:"Failed to write audio data to file"];
// Free resources
@@ -158,7 +160,7 @@ static OSStatus complexInputDataProc(AudioConverterRef inAudioConver
memcpy(ioData,
recorderStruct->sourceBuffer,
sizeof(AudioBufferList) + (recorderStruct->sourceBuffer->mNumberBuffers-1)*sizeof(AudioBuffer));
sizeof(AudioBufferList)+(recorderStruct->sourceBuffer->mNumberBuffers-1)*sizeof(AudioBuffer));
recorderStruct->sourceBuffer = NULL;
return noErr;
+13
View File
@@ -27,3 +27,16 @@ THE SOFTWARE.
Initial release.
Components include: EZAudioFile, EZAudioPlot, EZAudioPlotGL, EZMicrophone, EZOutput, and EZRecorder.
Provided 6 example projects: CoreGraphicsWaveform, OpenGLWaveform, WaveformFromFile, PassThrough, Record, and PlayFile.
0.0.2
Fix for Cocoapod spec. Forgot to include files with .c extension.
0.0.3
Changing EZAudioPlot and EZAudioPlotGL to scroll for the EZPlotTypeRolling instead of wiping the screen clean when hitting the end
Allowed EZMicrophone EZOutput to have custom AudioStreamBasicDescription setters
Fixed bug in EZAudioFile's getWaveformData function where it was not exiting after sending back cached waveform data (rereading from the audio file)
Added stereo support for EZMicrophone, EZAudioFile, EZRecorder, and EZOutput
Added more memory cleanup for EZAudioFile
Added adjustable rolling length for EZAudioPlot and EZAudioPlotGL so those rolling graphs can now range from 128 to 8192 whereas before it was fixed at 1024
Added adjustable resolution for waveform data coming from the EZAudioFile so output from the getWaveformDataWithCompletionBlock: function can literally be of any size. Try 128 for a low resolution waveform or 8192 for a much higher resolution waveform.
Added quick fix for EZOutput to properly route stereo data coming from a circular buffer datasource. Next version (0.0.4) needs to add EZConverter to allow quick conversions between non-interleaved and interleaved formats.
+1 -1
View File
@@ -23,4 +23,4 @@ THE SOFTWARE.
==========================================================================================
0.0.1
0.0.2
@@ -19,4 +19,7 @@
<FileRef
location = "group:EZAudioPassThroughExample/EZAudioPassThroughExample.xcodeproj">
</FileRef>
<FileRef
location = "group:EZAudioFFTExample/EZAudioFFTExample.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,610 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
9417A8F71871492000D9D37B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A8F61871492000D9D37B /* Cocoa.framework */; };
9417A9011871492000D9D37B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9417A8FF1871492000D9D37B /* InfoPlist.strings */; };
9417A9031871492000D9D37B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9021871492000D9D37B /* main.m */; };
9417A9071871492100D9D37B /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9051871492100D9D37B /* Credits.rtf */; };
9417A90A1871492100D9D37B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9091871492100D9D37B /* AppDelegate.m */; };
9417A90D1871492100D9D37B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9417A90B1871492100D9D37B /* MainMenu.xib */; };
9417A90F1871492100D9D37B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9417A90E1871492100D9D37B /* Images.xcassets */; };
9417A9161871492100D9D37B /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A9151871492100D9D37B /* XCTest.framework */; };
9417A9171871492100D9D37B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A8F61871492000D9D37B /* Cocoa.framework */; };
9417A91F1871492100D9D37B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9417A91D1871492100D9D37B /* InfoPlist.strings */; };
9417A9211871492100D9D37B /* EZAudioFFTExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9201871492100D9D37B /* EZAudioFFTExampleTests.m */; };
9417A9441871493900D9D37B /* AEFloatConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A92C1871493900D9D37B /* AEFloatConverter.m */; };
9417A9451871493900D9D37B /* EZAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A92E1871493900D9D37B /* EZAudio.m */; };
9417A9461871493900D9D37B /* EZAudioFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9301871493900D9D37B /* EZAudioFile.m */; };
9417A9471871493900D9D37B /* EZAudioPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9321871493900D9D37B /* EZAudioPlot.m */; };
9417A9481871493900D9D37B /* EZAudioPlotGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9341871493900D9D37B /* EZAudioPlotGL.m */; };
9417A9491871493900D9D37B /* EZAudioPlotGLKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9361871493900D9D37B /* EZAudioPlotGLKViewController.m */; };
9417A94A1871493900D9D37B /* EZMicrophone.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9381871493900D9D37B /* EZMicrophone.m */; };
9417A94B1871493900D9D37B /* EZOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A93A1871493900D9D37B /* EZOutput.m */; };
9417A94C1871493900D9D37B /* EZPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A93C1871493900D9D37B /* EZPlot.m */; };
9417A94D1871493900D9D37B /* EZRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A93E1871493900D9D37B /* EZRecorder.m */; };
9417A94E1871493900D9D37B /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 9417A93F1871493900D9D37B /* TPCircularBuffer.c */; };
9417A94F1871493900D9D37B /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9421871493900D9D37B /* CHANGELOG */; };
9417A9501871493900D9D37B /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9431871493900D9D37B /* VERSION */; };
9417A954187149EA00D9D37B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A951187149EA00D9D37B /* AudioToolbox.framework */; };
9417A955187149EA00D9D37B /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A952187149EA00D9D37B /* AudioUnit.framework */; };
9417A956187149EA00D9D37B /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A953187149EA00D9D37B /* CoreAudio.framework */; };
9417A959187149F000D9D37B /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A957187149F000D9D37B /* GLKit.framework */; };
9417A95A187149F000D9D37B /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A958187149F000D9D37B /* OpenGL.framework */; };
9417A95C18714A1000D9D37B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A95B18714A1000D9D37B /* QuartzCore.framework */; };
9417A95E18714A2A00D9D37B /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A95D18714A2A00D9D37B /* Accelerate.framework */; };
9417A9D61872130200D9D37B /* FFTViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9D41872130200D9D37B /* FFTViewController.m */; };
9417A9D71872130200D9D37B /* FFTViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9D51872130200D9D37B /* FFTViewController.xib */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
9417A9181871492100D9D37B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 9417A8EB1871492000D9D37B /* Project object */;
proxyType = 1;
remoteGlobalIDString = 9417A8F21871492000D9D37B;
remoteInfo = EZAudioFFTExample;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
9417A8F31871492000D9D37B /* EZAudioFFTExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioFFTExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
9417A8F61871492000D9D37B /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
9417A8F91871492000D9D37B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
9417A8FA1871492000D9D37B /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
9417A8FB1871492000D9D37B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
9417A8FE1871492000D9D37B /* EZAudioFFTExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EZAudioFFTExample-Info.plist"; sourceTree = "<group>"; };
9417A9001871492000D9D37B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9417A9021871492000D9D37B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
9417A9041871492000D9D37B /* EZAudioFFTExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EZAudioFFTExample-Prefix.pch"; sourceTree = "<group>"; };
9417A9061871492100D9D37B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
9417A9081871492100D9D37B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
9417A9091871492100D9D37B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9417A90C1871492100D9D37B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
9417A90E1871492100D9D37B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
9417A9141871492100D9D37B /* EZAudioFFTExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EZAudioFFTExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
9417A9151871492100D9D37B /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
9417A91C1871492100D9D37B /* EZAudioFFTExampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EZAudioFFTExampleTests-Info.plist"; sourceTree = "<group>"; };
9417A91E1871492100D9D37B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9417A9201871492100D9D37B /* EZAudioFFTExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFTExampleTests.m; sourceTree = "<group>"; };
9417A92B1871493900D9D37B /* AEFloatConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEFloatConverter.h; sourceTree = "<group>"; };
9417A92C1871493900D9D37B /* AEFloatConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AEFloatConverter.m; sourceTree = "<group>"; };
9417A92D1871493900D9D37B /* EZAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudio.h; sourceTree = "<group>"; };
9417A92E1871493900D9D37B /* EZAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudio.m; sourceTree = "<group>"; };
9417A92F1871493900D9D37B /* EZAudioFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFile.h; sourceTree = "<group>"; };
9417A9301871493900D9D37B /* EZAudioFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFile.m; sourceTree = "<group>"; };
9417A9311871493900D9D37B /* EZAudioPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlot.h; sourceTree = "<group>"; };
9417A9321871493900D9D37B /* EZAudioPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlot.m; sourceTree = "<group>"; };
9417A9331871493900D9D37B /* EZAudioPlotGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGL.h; sourceTree = "<group>"; };
9417A9341871493900D9D37B /* EZAudioPlotGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGL.m; sourceTree = "<group>"; };
9417A9351871493900D9D37B /* EZAudioPlotGLKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGLKViewController.h; sourceTree = "<group>"; };
9417A9361871493900D9D37B /* EZAudioPlotGLKViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGLKViewController.m; sourceTree = "<group>"; };
9417A9371871493900D9D37B /* EZMicrophone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZMicrophone.h; sourceTree = "<group>"; };
9417A9381871493900D9D37B /* EZMicrophone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZMicrophone.m; sourceTree = "<group>"; };
9417A9391871493900D9D37B /* EZOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZOutput.h; sourceTree = "<group>"; };
9417A93A1871493900D9D37B /* EZOutput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZOutput.m; sourceTree = "<group>"; };
9417A93B1871493900D9D37B /* EZPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZPlot.h; sourceTree = "<group>"; };
9417A93C1871493900D9D37B /* EZPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZPlot.m; sourceTree = "<group>"; };
9417A93D1871493900D9D37B /* EZRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZRecorder.h; sourceTree = "<group>"; };
9417A93E1871493900D9D37B /* EZRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZRecorder.m; sourceTree = "<group>"; };
9417A93F1871493900D9D37B /* TPCircularBuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = TPCircularBuffer.c; sourceTree = "<group>"; };
9417A9401871493900D9D37B /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
9417A9421871493900D9D37B /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
9417A9431871493900D9D37B /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
9417A951187149EA00D9D37B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
9417A952187149EA00D9D37B /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
9417A953187149EA00D9D37B /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
9417A957187149F000D9D37B /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
9417A958187149F000D9D37B /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
9417A95B18714A1000D9D37B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
9417A95D18714A2A00D9D37B /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
9417A9D31872130200D9D37B /* FFTViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FFTViewController.h; sourceTree = "<group>"; };
9417A9D41872130200D9D37B /* FFTViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FFTViewController.m; sourceTree = "<group>"; };
9417A9D51872130200D9D37B /* FFTViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FFTViewController.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9417A8F01871492000D9D37B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9417A95E18714A2A00D9D37B /* Accelerate.framework in Frameworks */,
9417A95C18714A1000D9D37B /* QuartzCore.framework in Frameworks */,
9417A959187149F000D9D37B /* GLKit.framework in Frameworks */,
9417A95A187149F000D9D37B /* OpenGL.framework in Frameworks */,
9417A954187149EA00D9D37B /* AudioToolbox.framework in Frameworks */,
9417A955187149EA00D9D37B /* AudioUnit.framework in Frameworks */,
9417A956187149EA00D9D37B /* CoreAudio.framework in Frameworks */,
9417A8F71871492000D9D37B /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9417A9111871492100D9D37B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9417A9171871492100D9D37B /* Cocoa.framework in Frameworks */,
9417A9161871492100D9D37B /* XCTest.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9417A8EA1871492000D9D37B = {
isa = PBXGroup;
children = (
9417A8FC1871492000D9D37B /* EZAudioFFTExample */,
9417A91A1871492100D9D37B /* EZAudioFFTExampleTests */,
9417A8F51871492000D9D37B /* Frameworks */,
9417A8F41871492000D9D37B /* Products */,
);
sourceTree = "<group>";
};
9417A8F41871492000D9D37B /* Products */ = {
isa = PBXGroup;
children = (
9417A8F31871492000D9D37B /* EZAudioFFTExample.app */,
9417A9141871492100D9D37B /* EZAudioFFTExampleTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
9417A8F51871492000D9D37B /* Frameworks */ = {
isa = PBXGroup;
children = (
9417A95D18714A2A00D9D37B /* Accelerate.framework */,
9417A95B18714A1000D9D37B /* QuartzCore.framework */,
9417A957187149F000D9D37B /* GLKit.framework */,
9417A958187149F000D9D37B /* OpenGL.framework */,
9417A951187149EA00D9D37B /* AudioToolbox.framework */,
9417A952187149EA00D9D37B /* AudioUnit.framework */,
9417A953187149EA00D9D37B /* CoreAudio.framework */,
9417A8F61871492000D9D37B /* Cocoa.framework */,
9417A9151871492100D9D37B /* XCTest.framework */,
9417A8F81871492000D9D37B /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
9417A8F81871492000D9D37B /* Other Frameworks */ = {
isa = PBXGroup;
children = (
9417A8F91871492000D9D37B /* AppKit.framework */,
9417A8FA1871492000D9D37B /* CoreData.framework */,
9417A8FB1871492000D9D37B /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
9417A8FC1871492000D9D37B /* EZAudioFFTExample */ = {
isa = PBXGroup;
children = (
9417A92A1871493900D9D37B /* EZAudio */,
9417A9081871492100D9D37B /* AppDelegate.h */,
9417A9091871492100D9D37B /* AppDelegate.m */,
9417A9D31872130200D9D37B /* FFTViewController.h */,
9417A9D41872130200D9D37B /* FFTViewController.m */,
9417A9D51872130200D9D37B /* FFTViewController.xib */,
9417A90B1871492100D9D37B /* MainMenu.xib */,
9417A90E1871492100D9D37B /* Images.xcassets */,
9417A8FD1871492000D9D37B /* Supporting Files */,
);
path = EZAudioFFTExample;
sourceTree = "<group>";
};
9417A8FD1871492000D9D37B /* Supporting Files */ = {
isa = PBXGroup;
children = (
9417A8FE1871492000D9D37B /* EZAudioFFTExample-Info.plist */,
9417A8FF1871492000D9D37B /* InfoPlist.strings */,
9417A9021871492000D9D37B /* main.m */,
9417A9041871492000D9D37B /* EZAudioFFTExample-Prefix.pch */,
9417A9051871492100D9D37B /* Credits.rtf */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
9417A91A1871492100D9D37B /* EZAudioFFTExampleTests */ = {
isa = PBXGroup;
children = (
9417A9201871492100D9D37B /* EZAudioFFTExampleTests.m */,
9417A91B1871492100D9D37B /* Supporting Files */,
);
path = EZAudioFFTExampleTests;
sourceTree = "<group>";
};
9417A91B1871492100D9D37B /* Supporting Files */ = {
isa = PBXGroup;
children = (
9417A91C1871492100D9D37B /* EZAudioFFTExampleTests-Info.plist */,
9417A91D1871492100D9D37B /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
9417A92A1871493900D9D37B /* EZAudio */ = {
isa = PBXGroup;
children = (
9417A92B1871493900D9D37B /* AEFloatConverter.h */,
9417A92C1871493900D9D37B /* AEFloatConverter.m */,
9417A92D1871493900D9D37B /* EZAudio.h */,
9417A92E1871493900D9D37B /* EZAudio.m */,
9417A92F1871493900D9D37B /* EZAudioFile.h */,
9417A9301871493900D9D37B /* EZAudioFile.m */,
9417A9311871493900D9D37B /* EZAudioPlot.h */,
9417A9321871493900D9D37B /* EZAudioPlot.m */,
9417A9331871493900D9D37B /* EZAudioPlotGL.h */,
9417A9341871493900D9D37B /* EZAudioPlotGL.m */,
9417A9351871493900D9D37B /* EZAudioPlotGLKViewController.h */,
9417A9361871493900D9D37B /* EZAudioPlotGLKViewController.m */,
9417A9371871493900D9D37B /* EZMicrophone.h */,
9417A9381871493900D9D37B /* EZMicrophone.m */,
9417A9391871493900D9D37B /* EZOutput.h */,
9417A93A1871493900D9D37B /* EZOutput.m */,
9417A93B1871493900D9D37B /* EZPlot.h */,
9417A93C1871493900D9D37B /* EZPlot.m */,
9417A93D1871493900D9D37B /* EZRecorder.h */,
9417A93E1871493900D9D37B /* EZRecorder.m */,
9417A93F1871493900D9D37B /* TPCircularBuffer.c */,
9417A9401871493900D9D37B /* TPCircularBuffer.h */,
9417A9411871493900D9D37B /* VERSION */,
);
name = EZAudio;
path = ../../../../EZAudio;
sourceTree = "<group>";
};
9417A9411871493900D9D37B /* VERSION */ = {
isa = PBXGroup;
children = (
9417A9421871493900D9D37B /* CHANGELOG */,
9417A9431871493900D9D37B /* VERSION */,
);
path = VERSION;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
9417A8F21871492000D9D37B /* EZAudioFFTExample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9417A9241871492100D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExample" */;
buildPhases = (
9417A8EF1871492000D9D37B /* Sources */,
9417A8F01871492000D9D37B /* Frameworks */,
9417A8F11871492000D9D37B /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = EZAudioFFTExample;
productName = EZAudioFFTExample;
productReference = 9417A8F31871492000D9D37B /* EZAudioFFTExample.app */;
productType = "com.apple.product-type.application";
};
9417A9131871492100D9D37B /* EZAudioFFTExampleTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9417A9271871492100D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExampleTests" */;
buildPhases = (
9417A9101871492100D9D37B /* Sources */,
9417A9111871492100D9D37B /* Frameworks */,
9417A9121871492100D9D37B /* Resources */,
);
buildRules = (
);
dependencies = (
9417A9191871492100D9D37B /* PBXTargetDependency */,
);
name = EZAudioFFTExampleTests;
productName = EZAudioFFTExampleTests;
productReference = 9417A9141871492100D9D37B /* EZAudioFFTExampleTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9417A8EB1871492000D9D37B /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = "Syed Haris Ali";
TargetAttributes = {
9417A9131871492100D9D37B = {
TestTargetID = 9417A8F21871492000D9D37B;
};
};
};
buildConfigurationList = 9417A8EE1871492000D9D37B /* Build configuration list for PBXProject "EZAudioFFTExample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 9417A8EA1871492000D9D37B;
productRefGroup = 9417A8F41871492000D9D37B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
9417A8F21871492000D9D37B /* EZAudioFFTExample */,
9417A9131871492100D9D37B /* EZAudioFFTExampleTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
9417A8F11871492000D9D37B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A9011871492000D9D37B /* InfoPlist.strings in Resources */,
9417A9D71872130200D9D37B /* FFTViewController.xib in Resources */,
9417A90F1871492100D9D37B /* Images.xcassets in Resources */,
9417A9071871492100D9D37B /* Credits.rtf in Resources */,
9417A9501871493900D9D37B /* VERSION in Resources */,
9417A90D1871492100D9D37B /* MainMenu.xib in Resources */,
9417A94F1871493900D9D37B /* CHANGELOG in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9417A9121871492100D9D37B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A91F1871492100D9D37B /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
9417A8EF1871492000D9D37B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A94D1871493900D9D37B /* EZRecorder.m in Sources */,
9417A9471871493900D9D37B /* EZAudioPlot.m in Sources */,
9417A94C1871493900D9D37B /* EZPlot.m in Sources */,
9417A9D61872130200D9D37B /* FFTViewController.m in Sources */,
9417A9441871493900D9D37B /* AEFloatConverter.m in Sources */,
9417A94A1871493900D9D37B /* EZMicrophone.m in Sources */,
9417A94B1871493900D9D37B /* EZOutput.m in Sources */,
9417A9451871493900D9D37B /* EZAudio.m in Sources */,
9417A94E1871493900D9D37B /* TPCircularBuffer.c in Sources */,
9417A9481871493900D9D37B /* EZAudioPlotGL.m in Sources */,
9417A9461871493900D9D37B /* EZAudioFile.m in Sources */,
9417A90A1871492100D9D37B /* AppDelegate.m in Sources */,
9417A9491871493900D9D37B /* EZAudioPlotGLKViewController.m in Sources */,
9417A9031871492000D9D37B /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9417A9101871492100D9D37B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A9211871492100D9D37B /* EZAudioFFTExampleTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
9417A9191871492100D9D37B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 9417A8F21871492000D9D37B /* EZAudioFFTExample */;
targetProxy = 9417A9181871492100D9D37B /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
9417A8FF1871492000D9D37B /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
9417A9001871492000D9D37B /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
9417A9051871492100D9D37B /* Credits.rtf */ = {
isa = PBXVariantGroup;
children = (
9417A9061871492100D9D37B /* en */,
);
name = Credits.rtf;
sourceTree = "<group>";
};
9417A90B1871492100D9D37B /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
9417A90C1871492100D9D37B /* Base */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
9417A91D1871492100D9D37B /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
9417A91E1871492100D9D37B /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
9417A9221871492100D9D37B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
9417A9231871492100D9D37B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
SDKROOT = macosx;
};
name = Release;
};
9417A9251871492100D9D37B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExample/EZAudioFFTExample-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
9417A9261871492100D9D37B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExample/EZAudioFFTExample-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
9417A9281871492100D9D37B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EZAudioFFTExample.app/Contents/MacOS/EZAudioFFTExample";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "EZAudioFFTExampleTests/EZAudioFFTExampleTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
9417A9291871492100D9D37B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EZAudioFFTExample.app/Contents/MacOS/EZAudioFFTExample";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(DEVELOPER_FRAMEWORKS_DIR)",
"$(inherited)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExampleTests/EZAudioFFTExampleTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9417A8EE1871492000D9D37B /* Build configuration list for PBXProject "EZAudioFFTExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9417A9221871492100D9D37B /* Debug */,
9417A9231871492100D9D37B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9417A9241871492100D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9417A9251871492100D9D37B /* Debug */,
9417A9261871492100D9D37B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9417A9271871492100D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExampleTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9417A9281871492100D9D37B /* Debug */,
9417A9291871492100D9D37B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 9417A8EB1871492000D9D37B /* Project object */;
}
@@ -0,0 +1,39 @@
//
// AppDelegate.h
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Cocoa/Cocoa.h>
#import "FFTViewController.h"
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window;
/**
The FFTViewController
*/
@property (nonatomic,strong) FFTViewController *fftViewController;
@end
@@ -0,0 +1,43 @@
//
// AppDelegate.m
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize fftViewController;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Swap in our view controller in the window's content view
self.fftViewController = [[FFTViewController alloc] init];
// Resize view controller to content view's current size
self.fftViewController.view.frame = [self.window.contentView frame];
// Add resizing flags to make the view controller resize with the window
self.fftViewController.view.autoresizingMask = (NSViewWidthSizable|NSViewHeightSizable);
// Add in the core graphics view controller as subview
[self.window.contentView addSubview:self.fftViewController.view];
}
@end
@@ -0,0 +1,679 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="EZAudioFFTExample" id="56">
<menu key="submenu" title="EZAudioFFTExample" systemMenu="apple" id="57">
<items>
<menuItem title="About EZAudioFFTExample" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Preferences…" keyEquivalent="," id="129"/>
<menuItem isSeparatorItem="YES" id="143">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Services" id="131">
<menu key="submenu" title="Services" systemMenu="services" id="130"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide EZAudioFFTExample" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="368"/>
</connections>
</menuItem>
<menuItem title="Show All" id="150">
<connections>
<action selector="unhideAllApplications:" target="-1" id="370"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit EZAudioFFTExample" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-3" id="449"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="83">
<menu key="submenu" title="File" id="81">
<items>
<menuItem title="New" keyEquivalent="n" id="82">
<connections>
<action selector="newDocument:" target="-1" id="373"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="72">
<connections>
<action selector="openDocument:" target="-1" id="374"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="124">
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
<items>
<menuItem title="Clear Menu" id="126">
<connections>
<action selector="clearRecentDocuments:" target="-1" id="127"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="79">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Close" keyEquivalent="w" id="73">
<connections>
<action selector="performClose:" target="-1" id="193"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="75">
<connections>
<action selector="saveDocument:" target="-1" id="362"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" id="112">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="revertDocumentToSaved:" target="-1" id="364"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="74">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Page Setup..." keyEquivalent="P" id="77">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="-1" id="87"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="78">
<connections>
<action selector="print:" target="-1" id="86"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207">
<connections>
<action selector="undo:" target="-1" id="223"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="215">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="redo:" target="-1" id="231"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="206">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Cut" keyEquivalent="x" id="199">
<connections>
<action selector="cut:" target="-1" id="228"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="197">
<connections>
<action selector="copy:" target="-1" id="224"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="203">
<connections>
<action selector="paste:" target="-1" id="226"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="486"/>
</connections>
</menuItem>
<menuItem title="Delete" id="202">
<connections>
<action selector="delete:" target="-1" id="235"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="198">
<connections>
<action selector="selectAll:" target="-1" id="232"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="214">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Find" id="218">
<menu key="submenu" title="Find" id="220">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
<connections>
<action selector="performFindPanelAction:" target="-1" id="241"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="535"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
<connections>
<action selector="performFindPanelAction:" target="-1" id="487"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="488"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221">
<connections>
<action selector="performFindPanelAction:" target="-1" id="489"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="216">
<menu key="submenu" title="Spelling and Grammar" id="200">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204">
<connections>
<action selector="showGuessPanel:" target="-1" id="230"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="201">
<connections>
<action selector="checkSpelling:" target="-1" id="225"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="453"/>
<menuItem title="Check Spelling While Typing" id="219">
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="346">
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="347"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="454">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="456"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="348">
<menu key="submenu" title="Substitutions" id="349">
<items>
<menuItem title="Show Substitutions" id="457">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="458"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="459"/>
<menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="460">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="461"/>
</connections>
</menuItem>
<menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="462">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="463"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="450">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="451">
<items>
<menuItem title="Make Upper Case" id="452">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="464"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="465">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="468"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="466">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="467"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196">
<connections>
<action selector="startSpeaking:" target="-1" id="233"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="195">
<connections>
<action selector="stopSpeaking:" target="-1" id="227"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="375">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="376">
<items>
<menuItem title="Font" id="377">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389">
<connections>
<action selector="orderFrontFontPanel:" target="420" id="424"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390">
<connections>
<action selector="addFontTrait:" target="420" id="421"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391">
<connections>
<action selector="addFontTrait:" target="420" id="422"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="392">
<connections>
<action selector="underline:" target="-1" id="432"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="393"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="394">
<connections>
<action selector="modifyFont:" target="420" id="425"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395">
<connections>
<action selector="modifyFont:" target="420" id="423"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="396"/>
<menuItem title="Kern" id="397">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="415">
<items>
<menuItem title="Use Default" id="416">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="-1" id="438"/>
</connections>
</menuItem>
<menuItem title="Use None" id="417">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="-1" id="441"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="418">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="-1" id="431"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="419">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="-1" id="435"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="398">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="411">
<items>
<menuItem title="Use Default" id="412">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="-1" id="439"/>
</connections>
</menuItem>
<menuItem title="Use None" id="413">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="-1" id="440"/>
</connections>
</menuItem>
<menuItem title="Use All" id="414">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="-1" id="434"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="399">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="405">
<items>
<menuItem title="Use Default" id="406">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="-1" id="437"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="407">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="-1" id="430"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="408">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="-1" id="429"/>
</connections>
</menuItem>
<menuItem title="Raise" id="409">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="-1" id="426"/>
</connections>
</menuItem>
<menuItem title="Lower" id="410">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="-1" id="427"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="400"/>
<menuItem title="Show Colors" keyEquivalent="C" id="401">
<connections>
<action selector="orderFrontColorPanel:" target="-1" id="433"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="402"/>
<menuItem title="Copy Style" keyEquivalent="c" id="403">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="-1" id="428"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="404">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="-1" id="436"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="496">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498">
<connections>
<action selector="alignLeft:" target="-1" id="524"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="499">
<connections>
<action selector="alignCenter:" target="-1" id="518"/>
</connections>
</menuItem>
<menuItem title="Justify" id="500">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="-1" id="523"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="501">
<connections>
<action selector="alignRight:" target="-1" id="521"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="508">
<items>
<menuItem title="Paragraph" enabled="NO" id="509">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="510">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="525"/>
</connections>
</menuItem>
<menuItem id="511">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="526"/>
</connections>
</menuItem>
<menuItem id="512">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="527"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="513"/>
<menuItem title="Selection" enabled="NO" id="514">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="515">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="-1" id="528"/>
</connections>
</menuItem>
<menuItem id="516">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="529"/>
</connections>
</menuItem>
<menuItem id="517">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="530"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="504"/>
<menuItem title="Show Ruler" id="505">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="-1" id="520"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="506">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="-1" id="522"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="507">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="-1" id="519"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="295">
<menu key="submenu" title="View" id="296">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="297">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="-1" id="366"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="298">
<connections>
<action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="19">
<menu key="submenu" title="Window" systemMenu="window" id="24">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="23">
<connections>
<action selector="performMiniaturize:" target="-1" id="37"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="239">
<connections>
<action selector="performZoom:" target="-1" id="240"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="92">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="490">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="EZAudioFFTExample Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="EZAudioFFTExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="PCv-Jm-jzO" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="PCv-Jm-jzO" secondAttribute="trailing" id="A2i-gs-EWe"/>
<constraint firstItem="PCv-Jm-jzO" firstAttribute="leading" secondItem="372" secondAttribute="leading" id="Gex-TR-aqy"/>
<constraint firstAttribute="bottom" secondItem="PCv-Jm-jzO" secondAttribute="bottom" id="Kqa-V4-EDP"/>
<constraint firstItem="PCv-Jm-jzO" firstAttribute="top" secondItem="372" secondAttribute="top" id="MeC-7d-nwe"/>
</constraints>
</view>
</window>
<customObject id="494" customClass="AppDelegate">
<connections>
<outlet property="audioPlot" destination="PCv-Jm-jzO" id="aGl-Mf-G6W"/>
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.sha.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2013 Syed Haris Ali. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
@@ -0,0 +1,9 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
@@ -0,0 +1,59 @@
//
// FFTViewController.h
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Cocoa/Cocoa.h>
/**
EZAudio
*/
#import "EZAudio.h"
/**
Accelerate
*/
#import <Accelerate/Accelerate.h>
/**
The FFTViewController demonstrates how to use the Accelerate framework to calculate the real-time FFT of audio data provided by an EZAudioMicrophone.
*/
@interface FFTViewController : NSViewController <EZMicrophoneDelegate>
#pragma mark - Components
/**
EZAudioPlot for frequency plot
*/
@property (nonatomic,weak) IBOutlet EZAudioPlot *audioPlotFreq;
/**
EZAudioPlot for time plot
*/
@property (nonatomic,weak) IBOutlet EZAudioPlotGL *audioPlotTime;
/**
Microphone
*/
@property (nonatomic,strong) EZMicrophone *microphone;
@end
@@ -0,0 +1,176 @@
//
// FFTViewController.m
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "FFTViewController.h"
@interface FFTViewController (){
COMPLEX_SPLIT _A;
FFTSetup _FFTSetup;
BOOL _isFFTSetup;
vDSP_Length _log2n;
}
@end
@implementation FFTViewController
@synthesize audioPlotFreq;
@synthesize audioPlotTime;
@synthesize microphone;
#pragma mark - Initialization
-(id)init {
self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil];
if(self){
[self initializeViewController];
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil];
if(self){
[self initializeViewController];
}
return self;
}
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:NSStringFromClass(self.class) bundle:nil];
if(self){
[self initializeViewController];
}
return self;
}
#pragma mark - Initialize View Controller
-(void)initializeViewController {
// Create an instance of the microphone and tell it to use this view controller instance as the delegate
self.microphone = [EZMicrophone microphoneWithDelegate:self
startsImmediately:YES];
}
#pragma mark - Customize the Audio Plot
-(void)awakeFromNib {
// Setup time domain audio plot
self.audioPlotTime.backgroundColor = [NSColor colorWithCalibratedRed: 0.569 green: 0.82 blue: 0.478 alpha: 1];
self.audioPlotTime.color = [NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.audioPlotTime.shouldFill = YES;
self.audioPlotTime.shouldMirror = YES;
self.audioPlotTime.plotType = EZPlotTypeRolling;
// Setup frequency domain audio plot
self.audioPlotFreq.backgroundColor = [NSColor colorWithCalibratedRed: 0.984 green: 0.471 blue: 0.525 alpha: 1];
self.audioPlotFreq.color = [NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.audioPlotFreq.shouldFill = YES;
self.audioPlotFreq.plotType = EZPlotTypeBuffer;
}
#pragma mark - FFT
/**
Adapted from http://batmobile.blogs.ilrt.org/fourier-transforms-on-an-iphone/
*/
-(void)createFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// Setup the length
_log2n = log2f(bufferSize);
// Calculate the weights array. This is a one-off operation.
_FFTSetup = vDSP_create_fftsetup(_log2n, FFT_RADIX2);
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Populate *window with the values for a hamming window function
float *window = (float *)malloc(sizeof(float)*bufferSize);
vDSP_hamm_window(window, bufferSize, 0);
// Window the samples
vDSP_vmul(data, 1, window, 1, data, 1, bufferSize);
// Define complex buffer
_A.realp = (float *) malloc(nOver2*sizeof(float));
_A.imagp = (float *) malloc(nOver2*sizeof(float));
}
-(void)updateFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Pack samples:
// C(re) -> A[n], C(im) -> A[n+1]
vDSP_ctoz((COMPLEX*)data, 2, &_A, 1, nOver2);
// Perform a forward FFT using fftSetup and A
// Results are returned in A
vDSP_fft_zrip(_FFTSetup, &_A, 1, _log2n, FFT_FORWARD);
// Convert COMPLEX_SPLIT A result to magnitudes
float amp[nOver2];
float maxMag = 0;
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
maxMag = mag > maxMag ? mag : maxMag;
}
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
// Bind the value to be less than 1.0 to fit in the graph
amp[i] = [EZAudio MAP:mag leftMin:0.0 leftMax:maxMag rightMin:0.0 rightMax:1.0];
}
// Update the frequency domain plot
[self.audioPlotFreq updateBuffer:amp
withBufferSize:nOver2];
}
#pragma mark - EZMicrophoneDelegate
-(void) microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels {
dispatch_async(dispatch_get_main_queue(), ^{
// Update time domain plot
[self.audioPlotTime updateBuffer:buffer[0]
withBufferSize:bufferSize];
// Setup the FFT if it's not already setup
if( !_isFFTSetup ){
[self createFFTWithBufferSize:bufferSize withAudioData:buffer[0]];
_isFFTSetup = YES;
}
// Get the FFT data
[self updateFFTWithBufferSize:bufferSize withAudioData:buffer[0]];
});
}
@end
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment version="1070" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="FFTViewController">
<connections>
<outlet property="audioPlotFreq" destination="4V2-1I-w64" id="SkA-7R-4V8"/>
<outlet property="audioPlotTime" destination="Zcc-CT-67u" id="lE0-d7-KUs"/>
<outlet property="view" destination="1" id="2"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customView id="1">
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<splitView dividerStyle="thin" translatesAutoresizingMaskIntoConstraints="NO" id="78b-rz-Bpl">
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView fixedFrame="YES" id="Zcc-CT-67u" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="0.0" width="480" height="132"/>
<autoresizingMask key="autoresizingMask"/>
</customView>
<customView fixedFrame="YES" id="4V2-1I-w64" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="133" width="480" height="139"/>
<autoresizingMask key="autoresizingMask"/>
</customView>
</subviews>
<holdingPriorities>
<real value="250"/>
<real value="250"/>
</holdingPriorities>
</splitView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="78b-rz-Bpl" secondAttribute="bottom" id="CZL-aU-xpy"/>
<constraint firstAttribute="trailing" secondItem="78b-rz-Bpl" secondAttribute="trailing" id="eXt-EL-upz"/>
<constraint firstItem="78b-rz-Bpl" firstAttribute="top" secondItem="1" secondAttribute="top" id="lFP-vc-nHC"/>
<constraint firstItem="78b-rz-Bpl" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="lWl-1T-nHB"/>
</constraints>
</customView>
</objects>
</document>
@@ -0,0 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,29 @@
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw9840\paperh8400
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
\f0\b\fs24 \cf0 Engineering:
\b0 \
Some people\
\
\b Human Interface Design:
\b0 \
Some other people\
\
\b Testing:
\b0 \
Hopefully not nobody\
\
\b Documentation:
\b0 \
Whoever\
\
\b With special thanks to:
\b0 \
Mom\
}
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
@@ -0,0 +1,14 @@
//
// main.m
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/29/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[])
{
return NSApplicationMain(argc, argv);
}
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.sha.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -0,0 +1,34 @@
//
// EZAudioFFTExampleTests.m
// EZAudioFFTExampleTests
//
// Created by Syed Haris Ali on 12/29/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface EZAudioFFTExampleTests : XCTestCase
@end
@implementation EZAudioFFTExampleTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
@@ -151,7 +151,7 @@ withNumberOfChannels:(UInt32)numberOfChannels {
-(void)microphone:(EZMicrophone *)microphone hasAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription {
// The AudioStreamBasicDescription of the microphone stream. This is useful when configuring the EZRecorder or telling another component what audio format type to expect.
// Here's a print function to allow you to inspect it a little easier
[EZAudio printASBD:audioStreamBasicDescription];
// [EZAudio printASBD:audioStreamBasicDescription];
}
-(void)microphone:(EZMicrophone *)microphone
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment version="1070" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
@@ -86,7 +86,7 @@
941D71C31864C457007D52D8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
941D71C51864C457007D52D8 /* EZAudioPassThroughExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EZAudioPassThroughExample-Prefix.pch"; sourceTree = "<group>"; };
941D71C71864C457007D52D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
941D71C91864C457007D52D8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
941D71C91864C457007D52D8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = EZAudioPassThroughExample/AppDelegate.h; sourceTree = SOURCE_ROOT; };
941D71CA1864C457007D52D8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
941D71CD1864C457007D52D8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
941D71CF1864C457007D52D8 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Cocoa/Cocoa.h>
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "AppDelegate.h"
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Cocoa/Cocoa.h>
@@ -21,6 +38,11 @@
*/
@property (nonatomic,weak) IBOutlet EZAudioPlotGL *audioPlot;
/**
The Microphone
*/
@property (nonatomic,strong) EZMicrophone *microphone;
#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)
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "PassThroughViewController.h"
@@ -14,6 +31,8 @@
@end
@implementation PassThroughViewController
@synthesize audioPlot;
@synthesize microphone;
#pragma mark - Initialization
-(id)init {
@@ -44,8 +63,7 @@
/**
Initialize the circular buffer
*/
[EZAudio circularBuffer:&_circularBuffer
withSize:1024];
[EZAudio circularBuffer:&_circularBuffer withSize:2048];
}
#pragma mark - Customize the Audio Plot
@@ -70,6 +88,7 @@
/**
Start the output
*/
[[EZOutput sharedOutput] setAudioStreamBasicDescription:[EZMicrophone sharedMicrophone].audioStreamBasicDescription];
[EZOutput sharedOutput].outputDataSource = self;
[[EZOutput sharedOutput] startPlayback];
@@ -188,8 +188,8 @@
94056F0D185BD83400EB94BA /* AppDelegate.m */,
94056F2E185BD86D00EB94BA /* PlayFileViewController.h */,
94056F2F185BD86D00EB94BA /* PlayFileViewController.m */,
9417A6D41865928C00D9D37B /* simple-drum-beat.wav */,
94056F30185BD86D00EB94BA /* PlayFileViewController.xib */,
9417A6D41865928C00D9D37B /* simple-drum-beat.wav */,
94056F0F185BD83400EB94BA /* MainMenu.xib */,
94056F12185BD83400EB94BA /* Images.xcassets */,
94056F01185BD83400EB94BA /* Supporting Files */,
@@ -167,14 +167,17 @@
// Stop playback
[[EZOutput sharedOutput] stopPlayback];
self.audioFile = [EZAudioFile audioFileWithURL:filePathURL andDelegate:self];
self.eof = NO;
self.filePathLabel.stringValue = filePathURL.lastPathComponent;
self.framePositionSlider.minValue = 0.0f;
self.framePositionSlider.maxValue = (double)self.audioFile.totalFrames;
self.playButton.state = NSOffState;
self.audioFile = [EZAudioFile audioFileWithURL:filePathURL andDelegate:self];
self.eof = NO;
self.filePathLabel.stringValue = filePathURL.lastPathComponent;
self.framePositionSlider.minValue = 0.0f;
self.framePositionSlider.maxValue = (double)self.audioFile.totalFrames;
self.playButton.state = NSOffState;
self.plotSegmentControl.selectedSegment = 1;
// Set the client format from the EZAudioFile on the output
[[EZOutput sharedOutput] setAudioStreamBasicDescription:self.audioFile.clientFormat];
// Plot the whole waveform
self.audioPlot.plotType = EZPlotTypeBuffer;
self.audioPlot.shouldFill = YES;
@@ -110,7 +110,7 @@
// Plot the whole waveform
self.audioPlot.plotType = EZPlotTypeBuffer;
self.audioPlot.shouldFill = YES;
self.audioPlot.shouldMirror = YES;
self.audioPlot.shouldMirror = YES;
[self.audioFile getWaveformDataWithCompletionBlock:^(float *waveformData, UInt32 length) {
[self.audioPlot updateBuffer:waveformData withBufferSize:length];
}];
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<deployment defaultVersion="1536" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
</dependencies>
<scenes>
@@ -8,7 +8,9 @@
#import "CoreGraphicsWaveformViewController.h"
@interface CoreGraphicsWaveformViewController ()
@interface CoreGraphicsWaveformViewController (){
float scale;
}
#pragma mark - UI Extras
@property (nonatomic,weak) IBOutlet UILabel *microphoneTextLabel;
@end
@@ -63,6 +65,10 @@
}
-(void)pinch:(UIPinchGestureRecognizer*)pinch {
}
#pragma mark - Actions
-(void)changePlotType:(id)sender {
NSInteger selectedSegment = [sender selectedSegmentIndex];
@@ -19,4 +19,7 @@
<FileRef
location = "group:EZAudioCoreGraphicsWaveformExample/../EZAudioPassThroughExample/EZAudioPassThroughExample.xcodeproj">
</FileRef>
<FileRef
location = "group:EZAudioFFTExample/EZAudioFFTExample.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,592 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
9417A96C1871E88300D9D37B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A96B1871E88300D9D37B /* Foundation.framework */; };
9417A96E1871E88300D9D37B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A96D1871E88300D9D37B /* CoreGraphics.framework */; };
9417A9701871E88300D9D37B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A96F1871E88300D9D37B /* UIKit.framework */; };
9417A9761871E88300D9D37B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9741871E88300D9D37B /* InfoPlist.strings */; };
9417A9781871E88300D9D37B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9771871E88300D9D37B /* main.m */; };
9417A97C1871E88300D9D37B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A97B1871E88300D9D37B /* AppDelegate.m */; };
9417A97F1871E88300D9D37B /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9417A97D1871E88300D9D37B /* Main_iPhone.storyboard */; };
9417A9821871E88300D9D37B /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9801871E88300D9D37B /* Main_iPad.storyboard */; };
9417A9871871E88300D9D37B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9861871E88300D9D37B /* Images.xcassets */; };
9417A98E1871E88300D9D37B /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A98D1871E88300D9D37B /* XCTest.framework */; };
9417A98F1871E88300D9D37B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A96B1871E88300D9D37B /* Foundation.framework */; };
9417A9901871E88300D9D37B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A96F1871E88300D9D37B /* UIKit.framework */; };
9417A9981871E88300D9D37B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9961871E88300D9D37B /* InfoPlist.strings */; };
9417A99A1871E88300D9D37B /* EZAudioFFTExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9991871E88300D9D37B /* EZAudioFFTExampleTests.m */; };
9417A9A41871E89500D9D37B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A9A31871E89500D9D37B /* AudioToolbox.framework */; };
9417A9A61871E8A100D9D37B /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A9A51871E8A100D9D37B /* GLKit.framework */; };
9417A9C11871E96300D9D37B /* AEFloatConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9A91871E96300D9D37B /* AEFloatConverter.m */; };
9417A9C21871E96300D9D37B /* EZAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9AB1871E96300D9D37B /* EZAudio.m */; };
9417A9C31871E96300D9D37B /* EZAudioFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9AD1871E96300D9D37B /* EZAudioFile.m */; };
9417A9C41871E96300D9D37B /* EZAudioPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9AF1871E96300D9D37B /* EZAudioPlot.m */; };
9417A9C51871E96300D9D37B /* EZAudioPlotGL.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9B11871E96300D9D37B /* EZAudioPlotGL.m */; };
9417A9C61871E96300D9D37B /* EZAudioPlotGLKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9B31871E96300D9D37B /* EZAudioPlotGLKViewController.m */; };
9417A9C71871E96300D9D37B /* EZMicrophone.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9B51871E96300D9D37B /* EZMicrophone.m */; };
9417A9C81871E96300D9D37B /* EZOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9B71871E96300D9D37B /* EZOutput.m */; };
9417A9C91871E96300D9D37B /* EZPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9B91871E96300D9D37B /* EZPlot.m */; };
9417A9CA1871E96300D9D37B /* EZRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9BB1871E96300D9D37B /* EZRecorder.m */; };
9417A9CB1871E96300D9D37B /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9BC1871E96300D9D37B /* TPCircularBuffer.c */; };
9417A9CC1871E96300D9D37B /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9BF1871E96300D9D37B /* CHANGELOG */; };
9417A9CD1871E96300D9D37B /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 9417A9C01871E96300D9D37B /* VERSION */; };
9417A9D01871E97D00D9D37B /* FFTViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9417A9CF1871E97D00D9D37B /* FFTViewController.m */; };
9417A9D21871EA5900D9D37B /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A9D11871EA5900D9D37B /* Accelerate.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
9417A9911871E88300D9D37B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 9417A9601871E88300D9D37B /* Project object */;
proxyType = 1;
remoteGlobalIDString = 9417A9671871E88300D9D37B;
remoteInfo = EZAudioFFTExample;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
9417A9681871E88300D9D37B /* EZAudioFFTExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioFFTExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
9417A96B1871E88300D9D37B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
9417A96D1871E88300D9D37B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
9417A96F1871E88300D9D37B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
9417A9731871E88300D9D37B /* EZAudioFFTExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EZAudioFFTExample-Info.plist"; sourceTree = "<group>"; };
9417A9751871E88300D9D37B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9417A9771871E88300D9D37B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
9417A9791871E88300D9D37B /* EZAudioFFTExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EZAudioFFTExample-Prefix.pch"; sourceTree = "<group>"; };
9417A97A1871E88300D9D37B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
9417A97B1871E88300D9D37B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9417A97E1871E88300D9D37B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPhone.storyboard; sourceTree = "<group>"; };
9417A9811871E88300D9D37B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPad.storyboard; sourceTree = "<group>"; };
9417A9861871E88300D9D37B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
9417A98C1871E88300D9D37B /* EZAudioFFTExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EZAudioFFTExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
9417A98D1871E88300D9D37B /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
9417A9951871E88300D9D37B /* EZAudioFFTExampleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EZAudioFFTExampleTests-Info.plist"; sourceTree = "<group>"; };
9417A9971871E88300D9D37B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9417A9991871E88300D9D37B /* EZAudioFFTExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFTExampleTests.m; sourceTree = "<group>"; };
9417A9A31871E89500D9D37B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
9417A9A51871E8A100D9D37B /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
9417A9A81871E96300D9D37B /* AEFloatConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEFloatConverter.h; sourceTree = "<group>"; };
9417A9A91871E96300D9D37B /* AEFloatConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AEFloatConverter.m; sourceTree = "<group>"; };
9417A9AA1871E96300D9D37B /* EZAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudio.h; sourceTree = "<group>"; };
9417A9AB1871E96300D9D37B /* EZAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudio.m; sourceTree = "<group>"; };
9417A9AC1871E96300D9D37B /* EZAudioFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFile.h; sourceTree = "<group>"; };
9417A9AD1871E96300D9D37B /* EZAudioFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFile.m; sourceTree = "<group>"; };
9417A9AE1871E96300D9D37B /* EZAudioPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlot.h; sourceTree = "<group>"; };
9417A9AF1871E96300D9D37B /* EZAudioPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlot.m; sourceTree = "<group>"; };
9417A9B01871E96300D9D37B /* EZAudioPlotGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGL.h; sourceTree = "<group>"; };
9417A9B11871E96300D9D37B /* EZAudioPlotGL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGL.m; sourceTree = "<group>"; };
9417A9B21871E96300D9D37B /* EZAudioPlotGLKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioPlotGLKViewController.h; sourceTree = "<group>"; };
9417A9B31871E96300D9D37B /* EZAudioPlotGLKViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioPlotGLKViewController.m; sourceTree = "<group>"; };
9417A9B41871E96300D9D37B /* EZMicrophone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZMicrophone.h; sourceTree = "<group>"; };
9417A9B51871E96300D9D37B /* EZMicrophone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZMicrophone.m; sourceTree = "<group>"; };
9417A9B61871E96300D9D37B /* EZOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZOutput.h; sourceTree = "<group>"; };
9417A9B71871E96300D9D37B /* EZOutput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZOutput.m; sourceTree = "<group>"; };
9417A9B81871E96300D9D37B /* EZPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZPlot.h; sourceTree = "<group>"; };
9417A9B91871E96300D9D37B /* EZPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZPlot.m; sourceTree = "<group>"; };
9417A9BA1871E96300D9D37B /* EZRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZRecorder.h; sourceTree = "<group>"; };
9417A9BB1871E96300D9D37B /* EZRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZRecorder.m; sourceTree = "<group>"; };
9417A9BC1871E96300D9D37B /* TPCircularBuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = TPCircularBuffer.c; sourceTree = "<group>"; };
9417A9BD1871E96300D9D37B /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
9417A9BF1871E96300D9D37B /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
9417A9C01871E96300D9D37B /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
9417A9CE1871E97D00D9D37B /* FFTViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FFTViewController.h; sourceTree = "<group>"; };
9417A9CF1871E97D00D9D37B /* FFTViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FFTViewController.m; sourceTree = "<group>"; };
9417A9D11871EA5900D9D37B /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9417A9651871E88300D9D37B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9417A9D21871EA5900D9D37B /* Accelerate.framework in Frameworks */,
9417A9A61871E8A100D9D37B /* GLKit.framework in Frameworks */,
9417A9A41871E89500D9D37B /* AudioToolbox.framework in Frameworks */,
9417A96E1871E88300D9D37B /* CoreGraphics.framework in Frameworks */,
9417A9701871E88300D9D37B /* UIKit.framework in Frameworks */,
9417A96C1871E88300D9D37B /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9417A9891871E88300D9D37B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9417A98E1871E88300D9D37B /* XCTest.framework in Frameworks */,
9417A9901871E88300D9D37B /* UIKit.framework in Frameworks */,
9417A98F1871E88300D9D37B /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9417A95F1871E88300D9D37B = {
isa = PBXGroup;
children = (
9417A9711871E88300D9D37B /* EZAudioFFTExample */,
9417A9931871E88300D9D37B /* EZAudioFFTExampleTests */,
9417A96A1871E88300D9D37B /* Frameworks */,
9417A9691871E88300D9D37B /* Products */,
);
sourceTree = "<group>";
};
9417A9691871E88300D9D37B /* Products */ = {
isa = PBXGroup;
children = (
9417A9681871E88300D9D37B /* EZAudioFFTExample.app */,
9417A98C1871E88300D9D37B /* EZAudioFFTExampleTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
9417A96A1871E88300D9D37B /* Frameworks */ = {
isa = PBXGroup;
children = (
9417A9D11871EA5900D9D37B /* Accelerate.framework */,
9417A9A51871E8A100D9D37B /* GLKit.framework */,
9417A9A31871E89500D9D37B /* AudioToolbox.framework */,
9417A96B1871E88300D9D37B /* Foundation.framework */,
9417A96D1871E88300D9D37B /* CoreGraphics.framework */,
9417A96F1871E88300D9D37B /* UIKit.framework */,
9417A98D1871E88300D9D37B /* XCTest.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
9417A9711871E88300D9D37B /* EZAudioFFTExample */ = {
isa = PBXGroup;
children = (
9417A9A71871E96300D9D37B /* EZAudio */,
9417A97A1871E88300D9D37B /* AppDelegate.h */,
9417A97B1871E88300D9D37B /* AppDelegate.m */,
9417A97D1871E88300D9D37B /* Main_iPhone.storyboard */,
9417A9801871E88300D9D37B /* Main_iPad.storyboard */,
9417A9CE1871E97D00D9D37B /* FFTViewController.h */,
9417A9CF1871E97D00D9D37B /* FFTViewController.m */,
9417A9861871E88300D9D37B /* Images.xcassets */,
9417A9721871E88300D9D37B /* Supporting Files */,
);
path = EZAudioFFTExample;
sourceTree = "<group>";
};
9417A9721871E88300D9D37B /* Supporting Files */ = {
isa = PBXGroup;
children = (
9417A9731871E88300D9D37B /* EZAudioFFTExample-Info.plist */,
9417A9741871E88300D9D37B /* InfoPlist.strings */,
9417A9771871E88300D9D37B /* main.m */,
9417A9791871E88300D9D37B /* EZAudioFFTExample-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
9417A9931871E88300D9D37B /* EZAudioFFTExampleTests */ = {
isa = PBXGroup;
children = (
9417A9991871E88300D9D37B /* EZAudioFFTExampleTests.m */,
9417A9941871E88300D9D37B /* Supporting Files */,
);
path = EZAudioFFTExampleTests;
sourceTree = "<group>";
};
9417A9941871E88300D9D37B /* Supporting Files */ = {
isa = PBXGroup;
children = (
9417A9951871E88300D9D37B /* EZAudioFFTExampleTests-Info.plist */,
9417A9961871E88300D9D37B /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
9417A9A71871E96300D9D37B /* EZAudio */ = {
isa = PBXGroup;
children = (
9417A9A81871E96300D9D37B /* AEFloatConverter.h */,
9417A9A91871E96300D9D37B /* AEFloatConverter.m */,
9417A9AA1871E96300D9D37B /* EZAudio.h */,
9417A9AB1871E96300D9D37B /* EZAudio.m */,
9417A9AC1871E96300D9D37B /* EZAudioFile.h */,
9417A9AD1871E96300D9D37B /* EZAudioFile.m */,
9417A9AE1871E96300D9D37B /* EZAudioPlot.h */,
9417A9AF1871E96300D9D37B /* EZAudioPlot.m */,
9417A9B01871E96300D9D37B /* EZAudioPlotGL.h */,
9417A9B11871E96300D9D37B /* EZAudioPlotGL.m */,
9417A9B21871E96300D9D37B /* EZAudioPlotGLKViewController.h */,
9417A9B31871E96300D9D37B /* EZAudioPlotGLKViewController.m */,
9417A9B41871E96300D9D37B /* EZMicrophone.h */,
9417A9B51871E96300D9D37B /* EZMicrophone.m */,
9417A9B61871E96300D9D37B /* EZOutput.h */,
9417A9B71871E96300D9D37B /* EZOutput.m */,
9417A9B81871E96300D9D37B /* EZPlot.h */,
9417A9B91871E96300D9D37B /* EZPlot.m */,
9417A9BA1871E96300D9D37B /* EZRecorder.h */,
9417A9BB1871E96300D9D37B /* EZRecorder.m */,
9417A9BC1871E96300D9D37B /* TPCircularBuffer.c */,
9417A9BD1871E96300D9D37B /* TPCircularBuffer.h */,
9417A9BE1871E96300D9D37B /* VERSION */,
);
name = EZAudio;
path = ../../../../EZAudio;
sourceTree = "<group>";
};
9417A9BE1871E96300D9D37B /* VERSION */ = {
isa = PBXGroup;
children = (
9417A9BF1871E96300D9D37B /* CHANGELOG */,
9417A9C01871E96300D9D37B /* VERSION */,
);
path = VERSION;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
9417A9671871E88300D9D37B /* EZAudioFFTExample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9417A99D1871E88300D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExample" */;
buildPhases = (
9417A9641871E88300D9D37B /* Sources */,
9417A9651871E88300D9D37B /* Frameworks */,
9417A9661871E88300D9D37B /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = EZAudioFFTExample;
productName = EZAudioFFTExample;
productReference = 9417A9681871E88300D9D37B /* EZAudioFFTExample.app */;
productType = "com.apple.product-type.application";
};
9417A98B1871E88300D9D37B /* EZAudioFFTExampleTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9417A9A01871E88300D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExampleTests" */;
buildPhases = (
9417A9881871E88300D9D37B /* Sources */,
9417A9891871E88300D9D37B /* Frameworks */,
9417A98A1871E88300D9D37B /* Resources */,
);
buildRules = (
);
dependencies = (
9417A9921871E88300D9D37B /* PBXTargetDependency */,
);
name = EZAudioFFTExampleTests;
productName = EZAudioFFTExampleTests;
productReference = 9417A98C1871E88300D9D37B /* EZAudioFFTExampleTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9417A9601871E88300D9D37B /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = "Syed Haris Ali";
TargetAttributes = {
9417A98B1871E88300D9D37B = {
TestTargetID = 9417A9671871E88300D9D37B;
};
};
};
buildConfigurationList = 9417A9631871E88300D9D37B /* Build configuration list for PBXProject "EZAudioFFTExample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 9417A95F1871E88300D9D37B;
productRefGroup = 9417A9691871E88300D9D37B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
9417A9671871E88300D9D37B /* EZAudioFFTExample */,
9417A98B1871E88300D9D37B /* EZAudioFFTExampleTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
9417A9661871E88300D9D37B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A9821871E88300D9D37B /* Main_iPad.storyboard in Resources */,
9417A9871871E88300D9D37B /* Images.xcassets in Resources */,
9417A97F1871E88300D9D37B /* Main_iPhone.storyboard in Resources */,
9417A9CD1871E96300D9D37B /* VERSION in Resources */,
9417A9761871E88300D9D37B /* InfoPlist.strings in Resources */,
9417A9CC1871E96300D9D37B /* CHANGELOG in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9417A98A1871E88300D9D37B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A9981871E88300D9D37B /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
9417A9641871E88300D9D37B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A9CB1871E96300D9D37B /* TPCircularBuffer.c in Sources */,
9417A9C81871E96300D9D37B /* EZOutput.m in Sources */,
9417A9C61871E96300D9D37B /* EZAudioPlotGLKViewController.m in Sources */,
9417A9C11871E96300D9D37B /* AEFloatConverter.m in Sources */,
9417A97C1871E88300D9D37B /* AppDelegate.m in Sources */,
9417A9C41871E96300D9D37B /* EZAudioPlot.m in Sources */,
9417A9C31871E96300D9D37B /* EZAudioFile.m in Sources */,
9417A9D01871E97D00D9D37B /* FFTViewController.m in Sources */,
9417A9C51871E96300D9D37B /* EZAudioPlotGL.m in Sources */,
9417A9781871E88300D9D37B /* main.m in Sources */,
9417A9C91871E96300D9D37B /* EZPlot.m in Sources */,
9417A9C71871E96300D9D37B /* EZMicrophone.m in Sources */,
9417A9CA1871E96300D9D37B /* EZRecorder.m in Sources */,
9417A9C21871E96300D9D37B /* EZAudio.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9417A9881871E88300D9D37B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9417A99A1871E88300D9D37B /* EZAudioFFTExampleTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
9417A9921871E88300D9D37B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 9417A9671871E88300D9D37B /* EZAudioFFTExample */;
targetProxy = 9417A9911871E88300D9D37B /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
9417A9741871E88300D9D37B /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
9417A9751871E88300D9D37B /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
9417A97D1871E88300D9D37B /* Main_iPhone.storyboard */ = {
isa = PBXVariantGroup;
children = (
9417A97E1871E88300D9D37B /* Base */,
);
name = Main_iPhone.storyboard;
sourceTree = "<group>";
};
9417A9801871E88300D9D37B /* Main_iPad.storyboard */ = {
isa = PBXVariantGroup;
children = (
9417A9811871E88300D9D37B /* Base */,
);
name = Main_iPad.storyboard;
sourceTree = "<group>";
};
9417A9961871E88300D9D37B /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
9417A9971871E88300D9D37B /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
9417A99B1871E88300D9D37B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
9417A99C1871E88300D9D37B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
9417A99E1871E88300D9D37B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExample/EZAudioFFTExample-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
9417A99F1871E88300D9D37B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExample/EZAudioFFTExample-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
9417A9A11871E88300D9D37B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EZAudioFFTExample.app/EZAudioFFTExample";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "EZAudioFFTExampleTests/EZAudioFFTExampleTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
9417A9A21871E88300D9D37B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EZAudioFFTExample.app/EZAudioFFTExample";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExampleTests/EZAudioFFTExampleTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9417A9631871E88300D9D37B /* Build configuration list for PBXProject "EZAudioFFTExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9417A99B1871E88300D9D37B /* Debug */,
9417A99C1871E88300D9D37B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9417A99D1871E88300D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9417A99E1871E88300D9D37B /* Debug */,
9417A99F1871E88300D9D37B /* Release */,
);
defaultConfigurationIsVisible = 0;
};
9417A9A01871E88300D9D37B /* Build configuration list for PBXNativeTarget "EZAudioFFTExampleTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9417A9A11871E88300D9D37B /* Debug */,
9417A9A21871E88300D9D37B /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 9417A9601871E88300D9D37B /* Project object */;
}
@@ -0,0 +1,32 @@
//
// AppDelegate.h
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
@@ -0,0 +1,63 @@
//
// AppDelegate.m
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FFTViewController" sceneMemberID="viewController">
<connections>
<outlet property="audioPlotFreq" destination="DSa-vR-ySS" id="JP5-yB-Jqo"/>
<outlet property="audioPlotTime" destination="Za4-u7-8h1" id="ox5-AQ-DaQ"/>
<outlet property="view" destination="e0f-bI-AGV" id="oLT-9I-NIK"/>
</connections>
</viewController>
<view contentMode="scaleToFill" id="e0f-bI-AGV">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Za4-u7-8h1" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="0.0" width="320" height="284"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" relation="lessThanOrEqual" constant="284" id="lUL-Pa-hHs"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DSa-vR-ySS" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="284" width="320" height="284"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" relation="lessThanOrEqual" priority="86" constant="284" id="aNL-Q8-MOw"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="DSa-vR-ySS" secondAttribute="trailing" id="FOI-4L-3b8"/>
<constraint firstItem="DSa-vR-ySS" firstAttribute="leading" secondItem="e0f-bI-AGV" secondAttribute="leading" id="LTm-AL-Oqz"/>
<constraint firstAttribute="trailing" secondItem="Za4-u7-8h1" secondAttribute="trailing" id="SLb-8B-cNK"/>
<constraint firstItem="DSa-vR-ySS" firstAttribute="top" secondItem="Za4-u7-8h1" secondAttribute="bottom" id="cef-HS-Uiw"/>
<constraint firstItem="Za4-u7-8h1" firstAttribute="leading" secondItem="e0f-bI-AGV" secondAttribute="leading" id="fe0-ef-NkA"/>
<constraint firstAttribute="bottom" secondItem="DSa-vR-ySS" secondAttribute="bottom" id="oDL-Qh-0Ei"/>
<constraint firstItem="Za4-u7-8h1" firstAttribute="top" secondItem="e0f-bI-AGV" secondAttribute="top" id="zKR-dO-8wP"/>
</constraints>
</view>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar" statusBarStyle="blackOpaque"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination"/>
</simulatedMetricsContainer>
</document>
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="ufC-wZ-h7g">
<objects>
<viewController id="vXZ-lx-hvc" customClass="FFTViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="SDG-bW-D9N"/>
<viewControllerLayoutGuide type="bottom" id="Ghx-UD-SsY"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0IN-AU-L5p" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="0.0" width="320" height="284"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" relation="lessThanOrEqual" constant="284" id="evV-xs-Een"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tRL-re-aMl" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="284" width="320" height="284"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" relation="lessThanOrEqual" priority="86" constant="284" id="G4S-hR-Wmj"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="tRL-re-aMl" secondAttribute="bottom" id="6Xx-qX-MTy"/>
<constraint firstItem="0IN-AU-L5p" firstAttribute="top" secondItem="kh9-bI-dsS" secondAttribute="top" id="83g-qr-GsR"/>
<constraint firstAttribute="trailing" secondItem="tRL-re-aMl" secondAttribute="trailing" id="eTI-rb-OrM"/>
<constraint firstAttribute="trailing" secondItem="0IN-AU-L5p" secondAttribute="trailing" id="iL0-3u-CeX"/>
<constraint firstItem="0IN-AU-L5p" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="j4O-TP-2Vf"/>
<constraint firstItem="tRL-re-aMl" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="jtj-vj-fPm"/>
<constraint firstItem="tRL-re-aMl" firstAttribute="top" secondItem="0IN-AU-L5p" secondAttribute="bottom" id="pZY-xg-Sb9"/>
</constraints>
</view>
<connections>
<outlet property="audioPlotFreq" destination="tRL-re-aMl" id="s8q-c6-u9E"/>
<outlet property="audioPlotTime" destination="0IN-AU-L5p" id="tej-Kb-ycI"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.sha.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>Main_iPhone</string>
<key>UIMainStoryboardFile~ipad</key>
<string>Main_iPad</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
@@ -0,0 +1,16 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
@@ -0,0 +1,59 @@
//
// FFTViewController.h
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <UIKit/UIKit.h>
/**
EZAudio
*/
#import "EZAudio.h"
/**
Accelerate
*/
#import <Accelerate/Accelerate.h>
/**
The FFTViewController demonstrates how to use the Accelerate framework to calculate the real-time FFT of audio data provided by an EZAudioMicrophone.
*/
@interface FFTViewController : UIViewController <EZMicrophoneDelegate>
#pragma mark - Components
/**
EZAudioPlot for frequency plot
*/
@property (nonatomic,weak) IBOutlet EZAudioPlot *audioPlotFreq;
/**
EZAudioPlot for time plot
*/
@property (nonatomic,weak) IBOutlet EZAudioPlotGL *audioPlotTime;
/**
Microphone
*/
@property (nonatomic,strong) EZMicrophone *microphone;
@end
@@ -0,0 +1,156 @@
//
// FFTViewController.m
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "FFTViewController.h"
@interface FFTViewController (){
COMPLEX_SPLIT _A;
FFTSetup _FFTSetup;
BOOL _isFFTSetup;
vDSP_Length _log2n;
}
@end
@implementation FFTViewController
@synthesize audioPlotFreq;
@synthesize audioPlotTime;
@synthesize microphone;
#pragma mark - Customize the Audio Plot
- (void)viewDidLoad
{
[super viewDidLoad];
/*
Customizing the audio plot's look
*/
// Setup time domain audio plot
self.audioPlotTime.backgroundColor = [UIColor colorWithRed: 0.569 green: 0.82 blue: 0.478 alpha: 1];
self.audioPlotTime.color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.audioPlotTime.shouldFill = YES;
self.audioPlotTime.shouldMirror = YES;
self.audioPlotTime.plotType = EZPlotTypeRolling;
// Setup frequency domain audio plot
self.audioPlotFreq.backgroundColor = [UIColor colorWithRed: 0.984 green: 0.471 blue: 0.525 alpha: 1];
self.audioPlotFreq.color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.audioPlotFreq.shouldFill = YES;
self.audioPlotFreq.plotType = EZPlotTypeBuffer;
/*
Start the microphone
*/
self.microphone = [EZMicrophone microphoneWithDelegate:self
startsImmediately:YES];
}
#pragma mark - FFT
/**
Adapted from http://batmobile.blogs.ilrt.org/fourier-transforms-on-an-iphone/
*/
-(void)createFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// Setup the length
_log2n = log2f(bufferSize);
// Calculate the weights array. This is a one-off operation.
_FFTSetup = vDSP_create_fftsetup(_log2n, FFT_RADIX2);
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Populate *window with the values for a hamming window function
float *window = (float *)malloc(sizeof(float)*bufferSize);
vDSP_hamm_window(window, bufferSize, 0);
// Window the samples
vDSP_vmul(data, 1, window, 1, data, 1, bufferSize);
free(window);
// Define complex buffer
_A.realp = (float *) malloc(nOver2*sizeof(float));
_A.imagp = (float *) malloc(nOver2*sizeof(float));
}
-(void)updateFFTWithBufferSize:(float)bufferSize withAudioData:(float*)data {
// For an FFT, numSamples must be a power of 2, i.e. is always even
int nOver2 = bufferSize/2;
// Pack samples:
// C(re) -> A[n], C(im) -> A[n+1]
vDSP_ctoz((COMPLEX*)data, 2, &_A, 1, nOver2);
// Perform a forward FFT using fftSetup and A
// Results are returned in A
vDSP_fft_zrip(_FFTSetup, &_A, 1, _log2n, FFT_FORWARD);
// Convert COMPLEX_SPLIT A result to magnitudes
float amp[nOver2];
float maxMag = 0;
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
maxMag = mag > maxMag ? mag : maxMag;
}
for(int i=0; i<nOver2; i++) {
// Calculate the magnitude
float mag = _A.realp[i]*_A.realp[i]+_A.imagp[i]*_A.imagp[i];
// Bind the value to be less than 1.0 to fit in the graph
amp[i] = [EZAudio MAP:mag leftMin:0.0 leftMax:maxMag rightMin:0.0 rightMax:1.0];
}
// Update the frequency domain plot
[self.audioPlotFreq updateBuffer:amp
withBufferSize:nOver2];
}
#pragma mark - EZMicrophoneDelegate
-(void) microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels {
dispatch_async(dispatch_get_main_queue(), ^{
// Update time domain plot
[self.audioPlotTime updateBuffer:buffer[0]
withBufferSize:bufferSize];
// Setup the FFT if it's not already setup
if( !_isFFTSetup ){
[self createFFTWithBufferSize:bufferSize withAudioData:buffer[0]];
_isFFTSetup = YES;
}
// Get the FFT data
[self updateFFTWithBufferSize:bufferSize withAudioData:buffer[0]];
});
}
@end
@@ -0,0 +1,53 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,51 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
@@ -0,0 +1,18 @@
//
// main.m
// EZAudioFFTExample
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.sha.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -0,0 +1,34 @@
//
// EZAudioFFTExampleTests.m
// EZAudioFFTExampleTests
//
// Created by Syed Haris Ali on 12/30/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface EZAudioFFTExampleTests : XCTestCase
@end
@implementation EZAudioFFTExampleTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <UIKit/UIKit.h>
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "AppDelegate.h"
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <UIKit/UIKit.h>
@@ -5,6 +5,23 @@
// Created by Syed Haris Ali on 12/20/13.
// Copyright (c) 2013 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "PassThroughViewController.h"
@@ -132,11 +132,14 @@
// Stop playback
[[EZOutput sharedOutput] stopPlayback];
self.audioFile = [EZAudioFile audioFileWithURL:filePathURL];
self.audioFile.audioFileDelegate = self;
self.eof = NO;
self.filePathLabel.text = filePathURL.lastPathComponent;
self.audioFile = [EZAudioFile audioFileWithURL:filePathURL];
self.audioFile.audioFileDelegate = self;
self.eof = NO;
self.filePathLabel.text = filePathURL.lastPathComponent;
self.framePositionSlider.maximumValue = (float)self.audioFile.totalFrames;
// Set the client format from the EZAudioFile on the output
[[EZOutput sharedOutput] setAudioStreamBasicDescription:self.audioFile.clientFormat];
// Plot the whole waveform
self.audioPlot.plotType = EZPlotTypeBuffer;
+29 -3
View File
@@ -43,7 +43,9 @@ An OpenGL-based, GPU-accelerated audio waveform plot capable of visualizing any
##Examples & Docs
Within this repo you'll find the examples for iOS and OSX to get you up to speed using each component and plugging them into each other. With just a few lines of code you'll be recording from the microphone, generating audio waveforms, and playing audio files like a boss. See the full Getting Started guide for an interactive look into each of components. Documentation will be hosted very soon on Cocoadocs!
Within this repo you'll find the examples for iOS and OSX to get you up to speed using each component and plugging them into each other. With just a few lines of code you'll be recording from the microphone, generating audio waveforms, and playing audio files like a boss. See the full Getting Started guide for an interactive look into each of components.
### Example Projects
**_EZAudioCoreGraphicsWaveformExample_**
@@ -69,6 +71,16 @@ Shows how to use the `EZAudioFile` and `EZAudioPlot` to display the audio wavefo
Shows how to use the `EZMicrophone`, `EZOutput`, and the `EZAudioPlotGL` to pass the microphone input to the output for playback while displaying the audio waveform (as a buffer or rolling plot) in real-time.
**_EZAudioFFTExample_**
Shows how to calculate the real-time FFT of the audio data coming from the `EZMicrophone` and the Accelerate framework. The audio data is plotted using the `EZAudioPlotGL` for the time domain plot and the `EZAudioPlot` for the frequency domain plot.
![alt text](https://s3-us-west-1.amazonaws.com/ezaudio-media/fftMacExample.png)
### Documentation
The official documentation for EZAudio can be found here: http://cocoadocs.org/docsets/EZAudio/0.0.2/
<br>You can also generate the docset yourself using appledocs by running the appledocs on the EZAudio source folder.
##Getting Started
*To see the full project page, interactive Getting Started guide, and Documentation go here:*
http://syedharisali.com/projects/EZAudio/getting-started
@@ -98,7 +110,16 @@ To begin using `EZAudio` you must first make sure you have the proper build requ
- GLKit
###Adding To Project
See full Getting Started guide: http://syedharisali.com/projects/EZAudio/getting-started
You can add EZAudio to your project in a few ways: <br><br>1.) The easiest way to use EZAudio is via <a href="http://cocoapods.org/", target="_blank">Cocoapods</a>. Simply add EZAudio to your <a href="http://guides.cocoapods.org/using/the-podfile.html", target="_blank">Podfile</a> like so:
`
pod 'EZAudio', '~> 0.0.2'
`
2.) Alternatively, you could clone or fork this repo and just drag and drop the source into your project.
*For more information see main project page:*
http://syedharisali.com/projects/EZAudio/getting-started
##Core Components
`EZAudio` currently offers four components that encompass a wide range of audio functionality. In addition to the functional aspects of these components such as pulling audio data, reading/writing from files, and performing playback they also take special care to hook into the interface components to allow developers to display visual feedback (see the Interface Components below).
@@ -530,7 +551,7 @@ Provides an audio waveform plot that uses OpenGL to perform the drawing. The API
####Creating An OpenGL Audio Plot
You can create an audio plot in the interface builder by dragging in a UIView on iOS or an NSOpenGLView on OSX onto your content area. Then change the custom class of the UIView/NSView to `EZAudioPlot`.
You can create an audio plot in the interface builder by dragging in a UIView on iOS or an NSOpenGLView on OSX onto your content area. Then change the custom class of the UIView/NSView to `EZAudioPlotGL`.
See full Getting Started page for how to: http://syedharisali.com/projects/EZAudio/getting-started
Alternatively, you can could create the `EZAudioPlotGL` programmatically
@@ -591,3 +612,8 @@ EZAudio is available under the MIT license. See the LICENSE file for more info.
Syed Haris Ali<br>
www.syedharisali.com<br>
syedhali07[at]gmail.com
##Acknowledgements
EZAudio could not have been created without the invaluable help of:
- <a href="http://atastypixel.com/blog/">Michael Tyson</a> for creating the <a href="http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/">TPCircularBuffer</a> and the <a href="http://theamazingaudioengine.com/">Amazing Audio Engine</a>'s `AEFloatConverter`.
- Chris Adamson and Kevin Avila for writing the amazing book <a href="http://www.amazon.com/Learning-Core-Audio-Hands-On-Programming/dp/0321636848">Learning Core Audio</a>