Compare commits

...

88 Commits

Author SHA1 Message Date
Syed Haris Ali 4900649287 added david's audioBufferList fix 2015-07-13 17:15:07 -07:00
Syed Haris Ali b99af54f31 style tweak 2015-07-13 17:08:54 -07:00
Syed Haris Ali b99f4b5366 Merge pull request #190 from dedjw/djw-audio-buffer-fix
Fix for audioBufferListWithNumberOfFrames: to match CoreAudio expectations
2015-07-13 17:07:41 -07:00
David Williams 78ea296cb2 Fix for audioBufferListWithNumberOfFrames:... to match CoreAudio expectations.
CoreAudio was giving a kAudioConverterErr_InvalidInputSize error when trying to
use bufferLists created by audioBufferListWithNumberOfFrames. The
mNumberBuffers, mNumberChannels, mDataByteSize needs to be self consistent.
Hopefully, this change fixes that.
Also, replaced the malloc/memset pair with calloc. memset was zeroing
only number of frames bytes, rather than the buffer size. Switching
to calloc ensures the buffer is zeroed out.
2015-07-13 16:46:22 -07:00
Syed Haris Ali 10b00754a9 removed debug line 2015-07-13 15:15:28 -07:00
Syed Haris Ali a35bb9a763 bumped version to 1.1.0 2015-07-13 15:14:27 -07:00
Syed Haris Ali 67199afe0b Update README.md 2015-07-13 15:11:58 -07:00
Syed Haris Ali 05cbfc8aa7 Merge pull request #189 from syedhali/ezfft_addition
Added EZAudioFFT, EZAudioFFTRolling, and fixed bug with appendBuffer: history funct
2015-07-13 13:22:01 -07:00
Syed Haris Ali 8732437e4a added music note utility method and updated examples 2015-07-13 13:19:07 -07:00
Syed Haris Ali 4b94107876 updated examples 2015-07-11 18:49:12 -07:00
Syed Haris Ali 65ee73736f added accelerate to list of dependencies 2015-07-11 17:40:11 -07:00
Syed Haris Ali 0cef3d22c9 added accelerate to list of dependencies 2015-07-11 17:39:22 -07:00
Syed Haris Ali f93e083af4 renamed to EZAudioFFT and added documentation 2015-07-11 17:34:36 -07:00
Syed Haris Ali 5404546901 adding EZFFT and fixed bug with appendBuffer utility function 2015-07-11 15:42:03 -07:00
Syed Haris Ali d08d7d6bfd Merge pull request #187 from syedhali/better_rolling_history_methods
Added more explicit methods for rolling history data structure
2015-07-11 12:36:42 -07:00
Syed Haris Ali e996ba60f8 added more explicit methods for rolling history data structure 2015-07-11 12:28:05 -07:00
Syed Haris Ali c148139fdd bumped version to 1.0.1 2015-07-09 13:46:38 -07:00
Syed Haris Ali 7a91b9b456 Merge pull request #180 from antonm76/master
EXC_BAD_ACCESS is fixed
2015-07-09 13:44:20 -07:00
Syed Haris Ali 2bd4993b31 Update EZAudioDevice.m 2015-07-06 19:25:47 -07:00
Syed Haris Ali d287995165 Update EZAudioDevice.h 2015-07-06 19:25:36 -07:00
Syed Haris Ali 7281f6cfcc updated podspec to 1.0.0 2015-07-06 19:20:07 -07:00
Syed Haris Ali 7ce2e67e91 Updated for 1.0.0 2015-07-06 19:17:32 -07:00
Syed Haris Ali 0279ce4fcc Added welcome message and projects request 2015-07-06 19:14:23 -07:00
Syed Haris Ali 3fc8fbd421 Added missing links 2015-07-06 18:57:26 -07:00
Syed Haris Ali 2736de1a8b Added description for EZAudioPlayer 2015-07-06 18:55:30 -07:00
Syed Haris Ali dd0139ed38 Added EZAudioPlayer 2015-07-06 18:34:44 -07:00
Syed Haris Ali 1b82915277 Update README.md 2015-07-06 18:15:33 -07:00
Syed Haris Ali 8d91213255 Add EZOutput effect chain explanation 2015-07-06 18:15:06 -07:00
Syed Haris Ali d2cc488dfb Update README.md 2015-07-06 17:56:22 -07:00
Syed Haris Ali 9a499a7c09 Update README.md 2015-07-06 17:36:48 -07:00
Syed Haris Ali 0c389efb0f Update README.md 2015-07-06 17:31:53 -07:00
Syed Haris Ali 89c8c808d3 Update README.md 2015-07-06 17:29:05 -07:00
Syed Haris Ali a6d3a02a91 Update README.md 2015-07-06 17:26:07 -07:00
Syed Haris Ali b52c819d02 Update README.md 2015-07-06 17:21:19 -07:00
Syed Haris Ali caf9062275 Added extended description of EZAudioDevice usage 2015-07-06 17:15:34 -07:00
Syed Haris Ali e77116aa1b Added EZAudioDevice + EZOutput device selection 2015-07-06 16:57:35 -07:00
Syed Haris Ali 67c9e3b1cb Updated FFT gif 2015-07-06 16:06:24 -07:00
Syed Haris Ali 4cc46687aa Update README.md 2015-07-06 15:57:03 -07:00
Syed Haris Ali 71337ca4bd Updated EZRecorder description and snippets 2015-07-06 15:53:49 -07:00
Syed Haris Ali 1e6cb271ed Finished up EZOutput description 2015-07-06 15:10:00 -07:00
Syed Haris Ali 5c8de38ad0 Updated EZOutputDataSource sine implementation
Added code snippet and description
2015-07-06 15:07:41 -07:00
Syed Haris Ali d3767afc76 Update README.md 2015-07-06 15:02:14 -07:00
Syed Haris Ali 2bdfe29e09 Updated EZAudioPlotGL description 2015-07-06 14:04:40 -07:00
Syed Haris Ali 0da69ab293 Updated interface builder instructions with gifs 2015-07-06 13:55:04 -07:00
Syed Haris Ali 834b1d9254 Updated EZAudioPlot and EZAudioPlotGL
Updated code snippets and descriptions
2015-07-06 12:23:22 -07:00
Syed Haris Ali e651d09f3d fixed stuff, removed circular buffer part of output 2015-07-06 00:30:31 -07:00
Syed Haris Ali 1adeea40b9 Merge pull request #184 from syedhali/new_readme
Updated EZAudioFile & EZMicrophone README
2015-07-06 00:27:45 -07:00
Syed Haris Ali 880a6c54e4 updated EZMicrophone code snippets 2015-07-06 00:26:40 -07:00
Syed Haris Ali 1ff2bc4ae9 updated more EZAudioFile code snippets 2015-07-06 00:20:02 -07:00
Syed Haris Ali 8636bc4cae updated EZAudioFile documentation and code snippets 2015-07-06 00:09:28 -07:00
Syed Haris Ali 021ae59035 updated audio file section 2015-07-05 23:52:09 -07:00
Syed Haris Ali cce54d802e updated example descriptions and component count 2015-07-05 23:43:47 -07:00
Syed Haris Ali 44f724b4ab changed title position 2015-07-05 23:33:57 -07:00
Syed Haris Ali 6631a15f66 added gifs to example projects 2015-07-05 23:29:22 -07:00
Syed Haris Ali b6e00fd8eb updated to 0.9.1 2015-07-05 21:51:18 -07:00
Syed Haris Ali 445e2fa530 Merge pull request #183 from syedhali/update_examples
Updated examples
2015-07-05 21:48:16 -07:00
Syed Haris Ali 3bb1b914a2 tiny tweak 2015-07-05 21:46:24 -07:00
Syed Haris Ali 6d00378ab0 removed warning 2015-07-05 21:45:50 -07:00
Syed Haris Ali ac07210263 bug fixes, UI updates, and added inspectable attributes 2015-07-05 21:45:00 -07:00
Syed Haris Ali 5920e7a61e added inspectable attributes to gl plot 2015-07-05 21:04:52 -07:00
Syed Haris Ali 4ef91004ea updated podspec to 0.9.0 2015-07-05 20:42:04 -07:00
Syed Haris Ali 1c6213c9c6 Merge branch 'master' of https://github.com/syedhali/EZAudio 2015-07-05 20:09:06 -07:00
Syed Haris Ali 59bd612164 updated examples for OSX 2015-07-05 20:08:57 -07:00
Syed Haris Ali b89b2254f0 Merge pull request #178 from hakanw/audio_file_reached_end_delegate_method 2015-07-05 15:30:43 -07:00
Håkan Waara 086ce50a54 document new audioplayer delegate method and fix styling nit 2015-07-05 23:18:53 +02:00
Syed Haris Ali 6684a874aa added current device for OSX, updated OSX examples to new window style 2015-07-05 13:23:34 -07:00
Syed Haris Ali 0c7226b3b0 updated podspec and readme to 0.8.0 2015-07-04 13:07:57 -07:00
Syed Haris Ali 9516768b1c Merge pull request #182 from syedhali/recorder_rewriter
Rewrote EZRecorder
2015-07-04 12:56:37 -07:00
Syed Haris Ali cf9dafc961 updated recording OSX example 2015-07-04 12:54:46 -07:00
Syed Haris Ali a74b1cf612 made current time readonly 2015-07-04 11:38:47 -07:00
Syed Haris Ali 1e7975e6cc little bit more cleanup 2015-07-04 11:33:41 -07:00
Syed Haris Ali cdd1372e30 added a ton of documentation 2015-07-03 21:29:44 -07:00
Syed Haris Ali 9f9c352f43 cleaned up header 2015-07-03 20:48:06 -07:00
Syed Haris Ali 9aab703069 updated recording example 2015-07-03 20:46:33 -07:00
Syed Haris Ali 3706a21e83 updated recorder to have API similar to EZAudioFile 2015-07-03 20:46:15 -07:00
Syed Haris Ali effa122525 updated client format doc 2015-07-03 20:44:54 -07:00
Syed Haris Ali 825e22e135 added play state delegate methods to mic 2015-07-03 20:40:49 -07:00
Syed Haris Ali 33c9ca84a2 added new initializers and class initializers 2015-07-03 18:31:41 -07:00
Syed Haris Ali 1a74a7def5 updating recorder to use same kind of API as EZAudioFile 2015-07-03 17:14:24 -07:00
Syed Haris Ali dcaadd43ce updated README 2015-07-03 10:49:08 -07:00
Syed Haris Ali 03db74e842 bumped version to 0.7.2 2015-07-03 10:44:56 -07:00
Syed Haris Ali ec19d44d86 Merge pull request #181 from syedhali/bug_fixes
Bug fixes
2015-07-03 10:43:37 -07:00
Syed Haris Ali 1e23f95dc2 added proper graph disposal 2015-07-03 10:41:58 -07:00
Syed Haris Ali 4d0b40d730 fixed crash in EZMicrophone due to running setup twice 2015-07-03 10:37:00 -07:00
Syed Haris Ali 732cf79963 Updated with The Amazing Audio Engine stuff 2015-07-02 12:36:15 -07:00
Syed Haris Ali 7e84f8744f Fixed typo 2015-07-02 12:25:08 -07:00
Anton Myshkovsky 5baeec30ce EXC_BAD_ACCESS is fixed
Occuring in initWithMicrophoneDelegate:withAudioStreamBasicDescription: during initial creation of EZMicrophone.
2015-07-02 15:30:14 +03:00
Håkan Waara 4f31db3d0e implement delegate method to find out when an audio file reached end, and also which file. 2015-07-02 11:59:02 +02:00
78 changed files with 6013 additions and 2306 deletions
+4 -6
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "EZAudio"
s.version = "0.7.1"
s.version = "1.1.1"
s.summary = "A simple, intuitive audio framework for iOS and OSX useful for anyone doing audio processing and/or audio-based visualizations."
s.homepage = "https://github.com/syedhali/EZAudio"
s.screenshots = "https://s3-us-west-1.amazonaws.com/ezaudio-media/EZAudioSummary.png"
@@ -10,11 +10,10 @@ Pod::Spec.new do |s|
s.osx.deployment_target = '10.8'
s.source = { :git => "https://github.com/syedhali/EZAudio.git", :tag => s.version }
s.exclude_files = [ 'EZAudio/VERSION', 'EZAudio/TPCircularBuffer.{h,c}' ]
s.ios.frameworks = 'AudioToolbox','AVFoundation','GLKit'
s.osx.frameworks = 'AudioToolbox','AudioUnit','CoreAudio','QuartzCore','OpenGL','GLKit'
s.ios.frameworks = 'AudioToolbox','AVFoundation','GLKit', 'Accelerate'
s.osx.frameworks = 'AudioToolbox','AudioUnit','CoreAudio','QuartzCore','OpenGL','GLKit', 'Accelerate'
s.requires_arc = true;
s.default_subspec = 'Full'
s.subspec 'Core' do |core|
core.source_files = 'EZAudio/*.{h,m,c}'
end
@@ -23,5 +22,4 @@ Pod::Spec.new do |s|
full.dependency 'TPCircularBuffer', '~> 0.0'
full.dependency 'EZAudio/Core'
end
end
end
+17 -4
View File
@@ -25,22 +25,35 @@
#import <Foundation/Foundation.h>
//------------------------------------------------------------------------------
#pragma mark - Core Components
//------------------------------------------------------------------------------
#import "EZAudioDevice.h"
#import "EZAudioFile.h"
#import "EZAudioFloatData.h"
#import "EZMicrophone.h"
#import "EZOutput.h"
#import "EZRecorder.h"
#import "EZAudioUtilities.h"
#pragma mark - Extended Components
#import "EZAudioPlayer.h"
//------------------------------------------------------------------------------
#pragma mark - Interface Components
//------------------------------------------------------------------------------
#import "EZPlot.h"
#import "EZAudioDisplayLink.h"
#import "EZAudioPlot.h"
#import "EZAudioPlotGL.h"
//------------------------------------------------------------------------------
#pragma mark - Utility Components
//------------------------------------------------------------------------------
#import "EZAudioFFT.h"
#import "EZAudioFloatConverter.h"
#import "EZAudioFloatData.h"
#import "EZAudioUtilities.h"
//------------------------------------------------------------------------------
/**
+36 -17
View File
@@ -1,10 +1,27 @@
//
// EZAudioDevice.h
// MicrophoneTest
// EZAudio
//
// Created by Syed Haris Ali on 4/3/15.
// Created by Syed Haris Ali on 6/25/15.
// Copyright (c) 2015 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 <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@@ -27,6 +44,22 @@
// @name Getting The Devices
//------------------------------------------------------------------------------
/**
Provides the current EZAudioDevice that is being used to pull input.
@return An EZAudioDevice instance representing the currently selected input device.
*/
+ (EZAudioDevice *)currentInputDevice;
//------------------------------------------------------------------------------
/**
Provides the current EZAudioDevice that is being used to output audio.
@return An EZAudioDevice instance representing the currently selected ouotput device.
*/
+ (EZAudioDevice *)currentOutputDevice;
//------------------------------------------------------------------------------
/**
Enumerates all the available input devices and returns the result in an NSArray of EZAudioDevice instances.
@return An NSArray containing EZAudioDevice instances, one for each available input device.
@@ -43,20 +76,6 @@
#if TARGET_OS_IPHONE
/**
Provides the current EZAudioDevice that is being used to pull input.
- iOS only
@return An EZAudioDevice instance representing the currently selected input device.
*/
+ (EZAudioDevice *)currentInputDevice;
/**
Provides the current EZAudioDevice that is being used to output audio.
- iOS only
@return An EZAudioDevice instance representing the currently selected ouotput device.
*/
+ (EZAudioDevice *)currentOutputDevice;
//------------------------------------------------------------------------------
/**
@@ -165,4 +184,4 @@
#endif
@end
@end
+62 -7
View File
@@ -1,10 +1,27 @@
//
// EZAudioDevice.m
// MicrophoneTest
// EZAudio
//
// Created by Syed Haris Ali on 4/3/15.
// Created by Syed Haris Ali on 6/25/15.
// Copyright (c) 2015 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 "EZAudioDevice.h"
#import "EZAudioUtilities.h"
@@ -217,11 +234,11 @@
AudioObjectPropertyAddress address = [self addressForPropertySelector:kAudioHardwarePropertyDevices];
UInt32 devicesDataSize;
[EZAudioUtilities checkResult:AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
&address,
0,
NULL,
&devicesDataSize)
operation:"Failed to get data size"];
&address,
0,
NULL,
&devicesDataSize)
operation:"Failed to get data size"];
// enumerate devices
NSInteger count = devicesDataSize / sizeof(AudioDeviceID);
@@ -271,6 +288,44 @@
//------------------------------------------------------------------------------
+ (EZAudioDevice *)deviceWithPropertySelector:(AudioObjectPropertySelector)propertySelector
{
AudioDeviceID deviceID;
UInt32 propSize = sizeof(AudioDeviceID);
AudioObjectPropertyAddress address = [self addressForPropertySelector:propertySelector];
[EZAudioUtilities checkResult:AudioObjectGetPropertyData(kAudioObjectSystemObject,
&address,
0,
NULL,
&propSize,
&deviceID)
operation:"Failed to get device device on OSX"];
EZAudioDevice *device = [[EZAudioDevice alloc] init];
device.deviceID = deviceID;
device.manufacturer = [self manufacturerForDeviceID:deviceID];
device.name = [self namePropertyForDeviceID:deviceID];
device.UID = [self UIDPropertyForDeviceID:deviceID];
device.inputChannelCount = [self channelCountForScope:kAudioObjectPropertyScopeInput forDeviceID:deviceID];
device.outputChannelCount = [self channelCountForScope:kAudioObjectPropertyScopeOutput forDeviceID:deviceID];
return device;
}
//------------------------------------------------------------------------------
+ (EZAudioDevice *)currentInputDevice
{
return [self deviceWithPropertySelector:kAudioHardwarePropertyDefaultInputDevice];
}
//------------------------------------------------------------------------------
+ (EZAudioDevice *)currentOutputDevice
{
return [self deviceWithPropertySelector:kAudioHardwarePropertyDefaultOutputDevice];
}
//------------------------------------------------------------------------------
+ (NSArray *)inputDevices
{
__block NSMutableArray *devices = [NSMutableArray array];
+392
View File
@@ -0,0 +1,392 @@
//
// EZAudioFFT.h
// EZAudio
//
// Created by Syed Haris Ali on 7/10/15.
// Copyright (c) 2015 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 <Foundation/Foundation.h>
#import <Accelerate/Accelerate.h>
@class EZAudioFFT;
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFTDelegate
//------------------------------------------------------------------------------
/**
The EZAudioFFTDelegate provides event callbacks for the EZAudioFFT (and subclasses such as the EZAudioFFTRolling) whenvever the FFT is computed.
*/
@protocol EZAudioFFTDelegate <NSObject>
@optional
///-----------------------------------------------------------
/// @name Getting FFT Output Data
///-----------------------------------------------------------
/**
Triggered when the EZAudioFFT computes an FFT from a buffer of input data. Provides an array of float data representing the computed FFT.
@param fft The EZAudioFFT instance that triggered the event.
@param fftData A float pointer representing the float array of FFT data.
@param bufferSize A vDSP_Length (unsigned long) representing the length of the float array.
*/
- (void) fft:(EZAudioFFT *)fft
updatedWithFFTData:(float *)fftData
bufferSize:(vDSP_Length)bufferSize;
@end
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFT
//------------------------------------------------------------------------------
/**
The EZAudioFFT provides a base class to quickly calculate the FFT of incoming audio data using the Accelerate framework. In addition, the EZAudioFFT contains an EZAudioFFTDelegate to receive an event anytime an FFT is computed.
*/
@interface EZAudioFFT : NSObject
//------------------------------------------------------------------------------
#pragma mark - Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Initializers
///-----------------------------------------------------------
/**
Initializes an EZAudioFFT (or subclass) instance with a maximum buffer size and sample rate. The sample rate is used specifically to calculate the `maxFrequency` property. If you don't care about the `maxFrequency` property then you can set the sample rate to 0.
@param maximumBufferSize A vDSP_Length (unsigned long) representing the maximum length of the incoming audio data.
@param sampleRate A float representing the sample rate of the incoming audio data.
@return A newly created EZAudioFFT (or subclass) instance.
*/
- (instancetype)initWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate;
//------------------------------------------------------------------------------
/**
Initializes an EZAudioFFT (or subclass) instance with a maximum buffer size, sample rate, and EZAudioFFTDelegate. The sample rate is used specifically to calculate the `maxFrequency` property. If you don't care about the `maxFrequency` property then you can set the sample rate to 0. The EZAudioFFTDelegate will act as a receive to get an event whenever the FFT is calculated.
@param maximumBufferSize A vDSP_Length (unsigned long) representing the maximum length of the incoming audio data.
@param sampleRate A float representing the sample rate of the incoming audio data.
@param delegate An EZAudioFFTDelegate to receive an event whenever the FFT is calculated.
@return A newly created EZAudioFFT (or subclass) instance.
*/
- (instancetype)initWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate;
//------------------------------------------------------------------------------
#pragma mark - Class Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Class Initializers
///-----------------------------------------------------------
/**
Class method to initialize an EZAudioFFT (or subclass) instance with a maximum buffer size and sample rate. The sample rate is used specifically to calculate the `maxFrequency` property. If you don't care about the `maxFrequency` property then you can set the sample rate to 0.
@param maximumBufferSize A vDSP_Length (unsigned long) representing the maximum length of the incoming audio data.
@param sampleRate A float representing the sample rate of the incoming audio data.
@return A newly created EZAudioFFT (or subclass) instance.
*/
+ (instancetype)fftWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate;
//------------------------------------------------------------------------------
/**
Class method to initialize an EZAudioFFT (or subclass) instance with a maximum buffer size, sample rate, and EZAudioFFTDelegate. The sample rate is used specifically to calculate the `maxFrequency` property. If you don't care about the `maxFrequency` property then you can set the sample rate to 0. The EZAudioFFTDelegate will act as a receive to get an event whenever the FFT is calculated.
@param maximumBufferSize A vDSP_Length (unsigned long) representing the maximum length of the incoming audio data.
@param sampleRate A float representing the sample rate of the incoming audio data.
@param delegate An EZAudioFFTDelegate to receive an event whenever the FFT is calculated.
@return A newly created EZAudioFFT (or subclass) instance.
*/
+ (instancetype)fftWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate;
//------------------------------------------------------------------------------
#pragma mark - Properties
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Properties
///-----------------------------------------------------------
/**
An EZAudioFFTDelegate to receive an event whenever the FFT is calculated.
*/
@property (weak, nonatomic) id<EZAudioFFTDelegate> delegate;
//------------------------------------------------------------------------------
/**
A COMPLEX_SPLIT data structure used to hold the FFT's imaginary and real components.
*/
@property (readonly, nonatomic) COMPLEX_SPLIT complexSplit;
//------------------------------------------------------------------------------
/**
A float array containing the last calculated FFT data.
*/
@property (readonly, nonatomic) float *fftData;
//------------------------------------------------------------------------------
/**
An FFTSetup data structure used to internally calculate the FFT using Accelerate.
*/
@property (readonly, nonatomic) FFTSetup fftSetup;
//------------------------------------------------------------------------------
/**
A float array containing the last calculated inverse FFT data (the time domain signal).
*/
@property (readonly, nonatomic) float *inversedFFTData;
//------------------------------------------------------------------------------
/**
A float representing the frequency with the highest energy is the last FFT calculation.
*/
@property (readonly, nonatomic) float maxFrequency;
//------------------------------------------------------------------------------
/**
A vDSP_Length (unsigned long) representing the index of the frequency with the highest energy is the last FFT calculation.
*/
@property (readonly, nonatomic) vDSP_Length maxFrequencyIndex;
//------------------------------------------------------------------------------
/**
A float representing the magnitude of the frequency with the highest energy is the last FFT calculation.
*/
@property (readonly, nonatomic) float maxFrequencyMagnitude;
//------------------------------------------------------------------------------
/**
A vDSP_Length (unsigned long) representing the maximum buffer size. This is the maximum length the incoming audio data in the `computeFFTWithBuffer:withBufferSize` method can be.
*/
@property (readonly, nonatomic) vDSP_Length maximumBufferSize;
//------------------------------------------------------------------------------
/**
A float representing the sample rate of the incoming audio data.
*/
@property (readwrite, nonatomic) float sampleRate;
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Computing The FFT
///-----------------------------------------------------------
/**
Computes the FFT for a float array representing an incoming audio signal. This will trigger the EZAudioFFTDelegate method `fft:updatedWithFFTData:bufferSize:`.
@param buffer A float array representing the audio data.
@param bufferSize The length of the float array of audio data.
@return A float array containing the computed FFT data. The length of the output will be half the incoming buffer (half the `bufferSize` argument).
*/
- (float *)computeFFTWithBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize;
//------------------------------------------------------------------------------
/**
Provides the frequency corresponding to an index in the last computed FFT data.
@param index A vDSP_Length (unsigned integer) representing the index of the frequency bin value you'd like to get
@return A float representing the frequency value at that index.
*/
- (float)frequencyAtIndex:(vDSP_Length)index;
//------------------------------------------------------------------------------
/**
Provides the magnitude of the frequenecy corresponding to an index in the last computed FFT data.
@param index A vDSP_Length (unsigned integer) representing the index of the frequency bin value you'd like to get
@return A float representing the frequency magnitude value at that index.
*/
- (float)frequencyMagnitudeAtIndex:(vDSP_Length)index;
@end
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFTRolling
//------------------------------------------------------------------------------
/**
The EZAudioFFTRolling, a subclass of EZAudioFFT, provides a class to calculate an FFT for an incoming audio signal while maintaining a history of audio data to allow much higher resolution FFTs. For instance, the EZMicrophone typically provides 512 frames at a time, but you would probably want to provide 2048 or 4096 frames for a decent looking FFT if you're trying to extract precise frequency components. You will typically be using this class for variable length FFTs instead of the EZAudioFFT base class.
*/
@interface EZAudioFFTRolling : EZAudioFFT
//------------------------------------------------------------------------------
#pragma mark - Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Initializers
///-----------------------------------------------------------
/**
Initializes an EZAudioFFTRolling instance with a window size and a sample rate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT and a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property). The history buffer size in this case is the `windowSize` * 8, which is pretty good for most cases.
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param sampleRate A float representing the sample rate of the incoming audio signal.
@return A newly created EZAudioFFTRolling instance.
*/
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate;
//------------------------------------------------------------------------------
/**
Initializes an EZAudioFFTRolling instance with a window size, a sample rate, and an EZAudioFFTDelegate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT, a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property), and an EZAudioFFTDelegate to receive a callback anytime the FFT is calculated. The history buffer size in this case is the `windowSize` * 8, which is pretty good for most cases.
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param sampleRate A float representing the sample rate of the incoming audio signal.
@param delegate An EZAudioFFTDelegate to receive an event whenever the FFT is calculated.
@return A newly created EZAudioFFTRolling instance.
*/
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Initializes an EZAudioFFTRolling instance with a window size, a history buffer size, and a sample rate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT, a history buffer size representing the maximum length of the sliding window's underlying circular buffer, and a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property).
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param historyBufferSize A vDSP_Length (unsigned long) representing the length of the history buffer. This should be AT LEAST the size of the window. A recommended value for this would be at least 8x greater than the `windowSize` argument.
@param sampleRate A float representing the sample rate of the incoming audio signal.
@return A newly created EZAudioFFTRolling instance.
*/
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate;
//------------------------------------------------------------------------------
/**
Initializes an EZAudioFFTRolling instance with a window size, a history buffer size, a sample rate, and an EZAudioFFTDelegate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT, a history buffer size representing the maximum length of the sliding window's underlying circular buffer, a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property), and an EZAudioFFTDelegate to receive a callback anytime the FFT is calculated.
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param historyBufferSize A vDSP_Length (unsigned long) representing the length of the history buffer. This should be AT LEAST the size of the window. A recommended value for this would be at least 8x greater than the `windowSize` argument.
@param sampleRate A float representing the sample rate of the incoming audio signal.
@param delegate An EZAudioFFTDelegate to receive an event whenever the FFT is calculated.
@return A newly created EZAudioFFTRolling instance.
*/
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate;
//------------------------------------------------------------------------------
#pragma mark - Class Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Class Initializers
///-----------------------------------------------------------
/**
Class method to initialize an EZAudioFFTRolling instance with a window size and a sample rate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT and a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property). The history buffer size in this case is the `windowSize` * 8, which is pretty good for most cases.
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param sampleRate A float representing the sample rate of the incoming audio signal.
@return A newly created EZAudioFFTRolling instance.
*/
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate;
//------------------------------------------------------------------------------
/**
Class method to initialize an EZAudioFFTRolling instance with a window size, a sample rate, and an EZAudioFFTDelegate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT, a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property), and an EZAudioFFTDelegate to receive a callback anytime the FFT is calculated. The history buffer size in this case is the `windowSize` * 8, which is pretty good for most cases.
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param sampleRate A float representing the sample rate of the incoming audio signal.
@param delegate An EZAudioFFTDelegate to receive an event whenever the FFT is calculated.
@return A newly created EZAudioFFTRolling instance.
*/
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Class method to initialize an EZAudioFFTRolling instance with a window size, a history buffer size, and a sample rate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT, a history buffer size representing the maximum length of the sliding window's underlying circular buffer, and a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property).
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param historyBufferSize A vDSP_Length (unsigned long) representing the length of the history buffer. This should be AT LEAST the size of the window. A recommended value for this would be at least 8x greater than the `windowSize` argument.
@param sampleRate A float representing the sample rate of the incoming audio signal.
@return A newly created EZAudioFFTRolling instance.
*/
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate;
//------------------------------------------------------------------------------
/**
Class method to initialize an EZAudioFFTRolling instance with a window size, a history buffer size, a sample rate, and an EZAudioFFTDelegate. The EZAudioFFTRolling has an internal EZPlotHistoryInfo data structure that writes audio data to a circular buffer and manages sliding windows of audio data to support efficient, large FFT calculations. Here you provide a window size that represents how many audio sample will be used to calculate the FFT, a history buffer size representing the maximum length of the sliding window's underlying circular buffer, a float representing the sample rate of the incoming audio (can be 0 if you don't care about the `maxFrequency` property), and an EZAudioFFTDelegate to receive a callback anytime the FFT is calculated.
@param windowSize A vDSP_Length (unsigned long) representing the size of the window (i.e. the resolution) of data that should be used to calculate the FFT. A typical value for this would be something like 1024 - 4096 (or higher for an even higher resolution FFT).
@param historyBufferSize A vDSP_Length (unsigned long) representing the length of the history buffer. This should be AT LEAST the size of the window. A recommended value for this would be at least 8x greater than the `windowSize` argument.
@param sampleRate A float representing the sample rate of the incoming audio signal.
@param delegate An EZAudioFFTDelegate to receive an event whenever the FFT is calculated.
@return A newly created EZAudioFFTRolling instance.
*/
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate;
//------------------------------------------------------------------------------
#pragma mark - Properties
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Properties
///-----------------------------------------------------------
/**
A vDSP_Length (unsigned long) representing the length of the FFT window.
*/
@property (readonly, nonatomic) vDSP_Length windowSize;
//------------------------------------------------------------------------------
/**
A float array representing the audio data in the internal circular buffer used to perform the FFT. This will increase as more data is appended to the internal circular buffer via the `computeFFTWithBuffer:withBufferSize:` method. The length of this array is the `timeDomainBufferSize` property.
*/
@property (readonly, nonatomic) float *timeDomainData;
//------------------------------------------------------------------------------
/**
A UInt32 representing the length of the audio data used to perform the FFT.
*/
@property (readonly, nonatomic) UInt32 timeDomainBufferSize;
@end
+444
View File
@@ -0,0 +1,444 @@
//
// EZAudioFFT.m
// EZAudio
//
// Created by Syed Haris Ali on 7/10/15.
// Copyright (c) 2015 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 "EZAudioFFT.h"
#import "EZAudioUtilities.h"
//------------------------------------------------------------------------------
#pragma mark - Data Structures
//------------------------------------------------------------------------------
typedef struct EZAudioFFTInfo
{
FFTSetup fftSetup;
COMPLEX_SPLIT complexA;
float *outFFTData;
vDSP_Length outFFTDataLength;
float *inversedFFTData;
vDSP_Length maxFrequencyIndex;
float maxFrequencyMangitude;
float maxFrequency;
} EZAudioFFTInfo;
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFT (Interface Extension)
//------------------------------------------------------------------------------
@interface EZAudioFFT ()
@property (assign, nonatomic) EZAudioFFTInfo *info;
@property (readwrite, nonatomic) vDSP_Length maximumBufferSize;
@end
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFT (Implementation)
//------------------------------------------------------------------------------
@implementation EZAudioFFT
//------------------------------------------------------------------------------
#pragma mark - Dealloc
//------------------------------------------------------------------------------
- (void)dealloc
{
vDSP_destroy_fftsetup(self.info->fftSetup);
free(self.info->complexA.realp);
free(self.info->complexA.imagp);
free(self.info->outFFTData);
free(self.info->inversedFFTData);
}
//------------------------------------------------------------------------------
#pragma mark - Initializers
//------------------------------------------------------------------------------
- (instancetype)initWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate
{
return [self initWithMaximumBufferSize:maximumBufferSize
sampleRate:sampleRate
delegate:nil];
}
//------------------------------------------------------------------------------
- (instancetype)initWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate
{
self = [super init];
if (self)
{
self.maximumBufferSize = (vDSP_Length)maximumBufferSize;
self.sampleRate = sampleRate;
self.delegate = delegate;
[self setup];
}
return self;
}
//------------------------------------------------------------------------------
#pragma mark - Class Initializers
//------------------------------------------------------------------------------
+ (instancetype)fftWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate
{
return [[self alloc] initWithMaximumBufferSize:maximumBufferSize
sampleRate:sampleRate];
}
//------------------------------------------------------------------------------
+ (instancetype)fftWithMaximumBufferSize:(vDSP_Length)maximumBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate
{
return [[self alloc] initWithMaximumBufferSize:maximumBufferSize
sampleRate:sampleRate
delegate:delegate];
}
//------------------------------------------------------------------------------
#pragma mark - Setup
//------------------------------------------------------------------------------
- (void)setup
{
NSAssert(self.maximumBufferSize > 0, @"Expected FFT buffer size to be greater than 0!");
//
// Initialize FFT
//
float maximumBufferSizeBytes = self.maximumBufferSize * sizeof(float);
self.info = (EZAudioFFTInfo *)calloc(1, sizeof(EZAudioFFTInfo));
vDSP_Length log2n = log2f(self.maximumBufferSize);
self.info->fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
long nOver2 = maximumBufferSizeBytes / 2;
size_t maximumSizePerComponentBytes = nOver2 * sizeof(float);
self.info->complexA.realp = (float *)malloc(maximumSizePerComponentBytes);
self.info->complexA.imagp = (float *)malloc(maximumSizePerComponentBytes);
self.info->outFFTData = (float *)malloc(maximumSizePerComponentBytes);
memset(self.info->outFFTData, 0, maximumSizePerComponentBytes);
self.info->inversedFFTData = (float *)malloc(maximumSizePerComponentBytes);
}
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
- (float *)computeFFTWithBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize
{
if (buffer == NULL)
{
return NULL;
}
//
// Calculate real + imaginary components and normalize
//
vDSP_Length log2n = log2f(bufferSize);
long nOver2 = bufferSize / 2;
float mFFTNormFactor = 10.0 / (2 * bufferSize);
vDSP_ctoz((COMPLEX*)buffer, 2, &(self.info->complexA), 1, nOver2);
vDSP_fft_zrip(self.info->fftSetup, &(self.info->complexA), 1, log2n, FFT_FORWARD);
vDSP_vsmul(self.info->complexA.realp, 1, &mFFTNormFactor, self.info->complexA.realp, 1, nOver2);
vDSP_vsmul(self.info->complexA.imagp, 1, &mFFTNormFactor, self.info->complexA.imagp, 1, nOver2);
vDSP_zvmags(&(self.info->complexA), 1, self.info->outFFTData, 1, nOver2);
vDSP_fft_zrip(self.info->fftSetup, &(self.info->complexA), 1, log2n, FFT_INVERSE);
vDSP_ztoc(&(self.info->complexA), 1, (COMPLEX *) self.info->inversedFFTData , 2, nOver2);
self.info->outFFTDataLength = nOver2;
//
// Calculate max freq
//
if (self.sampleRate > 0.0f)
{
vDSP_maxvi(self.info->outFFTData, 1, &self.info->maxFrequencyMangitude, &self.info->maxFrequencyIndex, nOver2);
self.info->maxFrequency = [self frequencyAtIndex:self.info->maxFrequencyIndex];
}
//
// Notify delegate
//
if ([self.delegate respondsToSelector:@selector(fft:updatedWithFFTData:bufferSize:)])
{
[self.delegate fft:self
updatedWithFFTData:self.info->outFFTData
bufferSize:nOver2];
}
//
// Return the FFT
//
return self.info->outFFTData;
}
//------------------------------------------------------------------------------
- (float)frequencyAtIndex:(vDSP_Length)index
{
if (!(self.info->outFFTData == NULL || self.sampleRate == 0.0f))
{
float nyquistMaxFreq = self.sampleRate / 2.0;
return ((float)index / (float)self.info->outFFTDataLength) * nyquistMaxFreq;
}
return NSNotFound;
}
//------------------------------------------------------------------------------
- (float)frequencyMagnitudeAtIndex:(vDSP_Length)index
{
if (self.info->outFFTData != NULL)
{
return self.info->outFFTData[index];
}
return NSNotFound;
}
//------------------------------------------------------------------------------
#pragma mark - Getters
//------------------------------------------------------------------------------
- (COMPLEX_SPLIT)complexSplit
{
return self.info->complexA;
}
//------------------------------------------------------------------------------
- (float *)fftData
{
return self.info->outFFTData;
}
//------------------------------------------------------------------------------
- (FFTSetup)fftSetup
{
return self.info->fftSetup;
}
//------------------------------------------------------------------------------
- (float *)inversedFFTData
{
return self.info->inversedFFTData;
}
//------------------------------------------------------------------------------
- (vDSP_Length)maxFrequencyIndex
{
return self.info->maxFrequencyIndex;
}
//------------------------------------------------------------------------------
- (float)maxFrequencyMagnitude
{
return self.info->maxFrequencyMangitude;
}
//------------------------------------------------------------------------------
- (float)maxFrequency
{
return self.info->maxFrequency;
}
@end
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFTRolling
//------------------------------------------------------------------------------
@interface EZAudioFFTRolling ()
@property (assign, nonatomic) EZPlotHistoryInfo *historyInfo;
@property (readwrite, nonatomic) vDSP_Length windowSize;
@end
@implementation EZAudioFFTRolling
//------------------------------------------------------------------------------
#pragma mark - Dealloc
//------------------------------------------------------------------------------
- (void)dealloc
{
[EZAudioUtilities freeHistoryInfo:self.historyInfo];
}
//------------------------------------------------------------------------------
#pragma mark - Initialization
//------------------------------------------------------------------------------
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate
{
return [self initWithWindowSize:windowSize
historyBufferSize:windowSize * 8
sampleRate:sampleRate
delegate:nil];
}
//------------------------------------------------------------------------------
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate
{
return [self initWithWindowSize:windowSize
historyBufferSize:windowSize * 8
sampleRate:sampleRate
delegate:delegate];
}
//------------------------------------------------------------------------------
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate
{
return [self initWithWindowSize:windowSize
historyBufferSize:historyBufferSize
sampleRate:sampleRate
delegate:nil];
}
//------------------------------------------------------------------------------
- (instancetype)initWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate
{
self = [super initWithMaximumBufferSize:historyBufferSize
sampleRate:sampleRate];
if (self)
{
self.delegate = delegate;
self.windowSize = windowSize;
//
// Allocate an appropriately sized history buffer in bytes
//
self.historyInfo = [EZAudioUtilities historyInfoWithDefaultLength:(UInt32)windowSize
maximumLength:(UInt32)historyBufferSize];
}
return self;
}
//------------------------------------------------------------------------------
#pragma mark - Class Initializers
//------------------------------------------------------------------------------
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate
{
return [[self alloc] initWithWindowSize:windowSize
sampleRate:sampleRate];
}
//------------------------------------------------------------------------------
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate
{
return [[self alloc] initWithWindowSize:windowSize
sampleRate:sampleRate
delegate:delegate];
}
//------------------------------------------------------------------------------
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate
{
return [[self alloc] initWithWindowSize:windowSize
historyBufferSize:historyBufferSize
sampleRate:sampleRate];
}
//------------------------------------------------------------------------------
+ (instancetype)fftWithWindowSize:(vDSP_Length)windowSize
historyBufferSize:(vDSP_Length)historyBufferSize
sampleRate:(float)sampleRate
delegate:(id<EZAudioFFTDelegate>)delegate
{
return [[self alloc] initWithWindowSize:windowSize
historyBufferSize:historyBufferSize
sampleRate:sampleRate
delegate:delegate];
}
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
- (float *)computeFFTWithBuffer:(float *)buffer
withBufferSize:(UInt32)bufferSize
{
if (buffer == NULL)
{
return NULL;
}
//
// Append buffer to history window
//
[EZAudioUtilities appendBuffer:buffer
withBufferSize:bufferSize
toHistoryInfo:self.historyInfo];
//
// Call super to calculate the FFT of the window
//
return [super computeFFTWithBuffer:self.historyInfo->buffer
withBufferSize:self.historyInfo->bufferSize];
}
//------------------------------------------------------------------------------
#pragma mark - Getters
//------------------------------------------------------------------------------
- (UInt32)timeDomainBufferSize
{
return self.historyInfo->bufferSize;
}
//------------------------------------------------------------------------------
- (float *)timeDomainData
{
return self.historyInfo->buffer;
}
@end
+15 -3
View File
@@ -65,12 +65,23 @@ typedef void (^EZAudioWaveformDataCompletionBlock)(float **waveformData, int len
//------------------------------------------------------------------------------
/**
Occurs when the audio file's internal seek position has been updated by the EZAudioFile functions `readFrames:audioBufferList:bufferSize:eof:` or `audioFile:updatedPosition:`. As of 0.8.0 this is the preferred method of listening for position updates on the audio file since a user may want the pull the currentTime, formattedCurrentTime, or the frame index from the EZAudioFile instance provided.
@param audioFile The instance of the EZAudio in which the change occured.
*/
- (void)audioFileUpdatedPosition:(EZAudioFile *)audioFile;
//------------------------------------------------------------------------------
/**
Occurs when the audio file's internal seek position has been updated by the EZAudioFile functions `readFrames:audioBufferList:bufferSize:eof:` or `audioFile:updatedPosition:`.
@param audioFile The instance of the EZAudio in which the change occured
@param framePosition The new frame index as a 64-bit signed integer
@deprecated This property is deprecated starting in version 0.8.0.
@note Please use `audioFileUpdatedPosition:` property instead.
*/
- (void)audioFile:(EZAudioFile *)audioFile updatedPosition:(SInt64)framePosition;
- (void)audioFile:(EZAudioFile *)audioFile
updatedPosition:(SInt64)framePosition __attribute__((deprecated));
@end
@@ -85,6 +96,7 @@ typedef void (^EZAudioWaveformDataCompletionBlock)(float **waveformData, int len
//------------------------------------------------------------------------------
#pragma mark - Properties
//------------------------------------------------------------------------------
/**
A EZAudioFileDelegate for the audio file that is used to return events such as new seek positions within the file and the read audio data as a float array.
*/
@@ -232,7 +244,7 @@ typedef void (^EZAudioWaveformDataCompletionBlock)(float **waveformData, int len
*/
/**
Provides the AudioStreamBasicDescription structure used within the app. The file's format will be converted to this format and then sent back as either a float array or a `AudioBufferList` pointer. For instance, the file on disk could be a 22.5 kHz, float format, but we might have an audio processing graph that has a 44.1 kHz, signed integer format that we'd like to interact with. The client format lets us set that 44.1 kHz format on the audio file to properly read samples from it with any interpolation or format conversion that must take place done automatically within the EZAudioFile `readFrames:audioBufferList:bufferSize:eof:` method. Default is stereo, non-interleaved, 44.1 kHz.
Provides the common AudioStreamBasicDescription that will be used for in-app interaction. The file's format will be converted to this format and then sent back as either a float array or a `AudioBufferList` pointer. For instance, the file on disk could be a 22.5 kHz, float format, but we might have an audio processing graph that has a 44.1 kHz, signed integer format that we'd like to interact with. The client format lets us set that 44.1 kHz format on the audio file to properly read samples from it with any interpolation or format conversion that must take place done automatically within the EZAudioFile `readFrames:audioBufferList:bufferSize:eof:` method. Default is stereo, non-interleaved, 44.1 kHz.
@warning This must be a linear PCM format!
@return An AudioStreamBasicDescription structure describing the format of the audio file.
*/
@@ -299,7 +311,7 @@ typedef void (^EZAudioWaveformDataCompletionBlock)(float **waveformData, int len
@note Please use `duration` property instead.
@return The total duration of the audio file as a Float32.
*/
@property (readonly) NSTimeInterval totalDuration __attribute__((deprecated));;
@property (readonly) NSTimeInterval totalDuration __attribute__((deprecated));
//------------------------------------------------------------------------------
+30 -5
View File
@@ -313,11 +313,24 @@ typedef struct
*bufferSize = frames;
*eof = frames == 0;
// notify delegate
//
// Notify delegate
//
if ([self.delegate respondsToSelector:@selector(audioFileUpdatedPosition:)])
{
[self.delegate audioFileUpdatedPosition:self];
}
//
// Deprecated, but supported until 1.0
//
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
if ([self.delegate respondsToSelector:@selector(audioFile:updatedPosition:)])
{
[self.delegate audioFile:self updatedPosition:self.frameIndex];
[self.delegate audioFile:self updatedPosition:[self frameIndex]];
}
#pragma GCC diagnostic pop
if ([self.delegate respondsToSelector:@selector(audioFile:readAudio:withBufferSize:withNumberOfChannels:)])
{
@@ -351,12 +364,24 @@ typedef struct
pthread_mutex_unlock(&_lock);
// notify delegate
//
// Notify delegate
//
if ([self.delegate respondsToSelector:@selector(audioFileUpdatedPosition:)])
{
[self.delegate audioFileUpdatedPosition:self];
}
//
// Deprecated, but supported until 1.0
//
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
if ([self.delegate respondsToSelector:@selector(audioFile:updatedPosition:)])
{
[self.delegate audioFile:self
updatedPosition:self.frameIndex];
[self.delegate audioFile:self updatedPosition:[self frameIndex]];
}
#pragma GCC diagnostic pop
}
}
+10 -1
View File
@@ -109,6 +109,15 @@ FOUNDATION_EXPORT NSString * const EZAudioPlayerDidSeekNotification;
updatedPosition:(SInt64)framePosition
inAudioFile:(EZAudioFile *)audioFile;
/**
Triggered by EZAudioPlayer's internal EZAudioFile's EZAudioFileDelegate callback and notifies the delegate that the end of the file has been reached.
@param audioPlayer The instance of the EZAudioPlayer that triggered the event
@param audioFile The instance of the EZAudioFile that the event was triggered from
*/
- (void)audioPlayer:(EZAudioPlayer *)audioPlayer
reachedEndOfAudioFile:(EZAudioFile *)audioFile;
@end
//------------------------------------------------------------------------------
@@ -411,4 +420,4 @@ FOUNDATION_EXPORT NSString * const EZAudioPlayerDidSeekNotification;
*/
- (void)seekToFrame:(SInt64)frame;
@end
@end
+7 -3
View File
@@ -372,6 +372,10 @@ NSString * const EZAudioPlayerDidSeekNotification = @"EZAudioPlayerDidSeekNotifi
audioBufferList:audioBufferList
bufferSize:&bufferSize
eof:&eof];
if (eof && [self.delegate respondsToSelector:@selector(audioPlayer:reachedEndOfAudioFile:)])
{
[self.delegate audioPlayer:self reachedEndOfAudioFile:self.audioFile];
}
if (eof && self.shouldLoop)
{
[self seekToFrame:0];
@@ -391,12 +395,12 @@ NSString * const EZAudioPlayerDidSeekNotification = @"EZAudioPlayerDidSeekNotifi
#pragma mark - EZAudioFileDelegate
//------------------------------------------------------------------------------
- (void)audioFile:(EZAudioFile *)audioFile updatedPosition:(SInt64)framePosition
- (void)audioFileUpdatedPosition:(EZAudioFile *)audioFile
{
if ([self.delegate respondsToSelector:@selector(audioPlayer:updatedPosition:inAudioFile:)])
{
[self.delegate audioPlayer:self
updatedPosition:framePosition
updatedPosition:[audioFile frameIndex]
inAudioFile:audioFile];
}
}
@@ -438,4 +442,4 @@ NSString * const EZAudioPlayerDidSeekNotification = @"EZAudioPlayerDidSeekNotifi
//------------------------------------------------------------------------------
@end
@end
+7
View File
@@ -156,6 +156,13 @@ FOUNDATION_EXPORT UInt32 const EZAudioPlotDefaultMaxHistoryBufferLength;
//------------------------------------------------------------------------------
/**
Called after the view has been created. Subclasses should use to add any additional methods needed instead of overriding the init methods.
*/
- (void)setupPlot;
//------------------------------------------------------------------------------
/**
Provides the default number of points that will be used to initialize the graph's points data structure that holds. Essentially the plot starts off as a flat line of this many points. Default is 100.
@return An int describing the initial number of points the plot should have when flat lined.
+17 -3
View File
@@ -151,11 +151,25 @@ UInt32 const EZAudioPlotDefaultMaxHistoryBufferLength = 8192;
self.backgroundColor = nil;
[self.layer insertSublayer:self.waveformLayer atIndex:0];
//
// Allow subclass to initialize plot
//
[self setupPlot];
self.points = calloc(EZAudioPlotDefaultMaxHistoryBufferLength, sizeof(CGPoint));
self.pointCount = [self initialPointCount];
[self redraw];
}
//------------------------------------------------------------------------------
- (void)setupPlot
{
//
// Override in subclass
//
}
//------------------------------------------------------------------------------
#pragma mark - Setup
//------------------------------------------------------------------------------
@@ -314,9 +328,9 @@ UInt32 const EZAudioPlotDefaultMaxHistoryBufferLength = 8192;
- (void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize
{
// append the buffer to the history
[EZAudioUtilities appendBuffer:buffer
withBufferSize:bufferSize
toHistoryInfo:self.historyInfo];
[EZAudioUtilities appendBufferRMS:buffer
withBufferSize:bufferSize
toHistoryInfo:self.historyInfo];
// copy samples
switch (self.plotType)
+35 -5
View File
@@ -64,21 +64,29 @@ typedef struct
The default background color of the plot. For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is a sweet looking green.
@warning On OSX, if you set the background to a value where the alpha component is 0 then the EZAudioPlotGL will automatically set its superview to be layer-backed.
*/
@property (nonatomic, strong) id backgroundColor;
#if TARGET_OS_IPHONE
@property (nonatomic, strong) IBInspectable UIColor *backgroundColor;
#elif TARGET_OS_MAC
@property (nonatomic, strong) IBInspectable NSColor *backgroundColor;
#endif
//------------------------------------------------------------------------------
/**
The default color of the plot's data (i.e. waveform, y-axis values). For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is white.
*/
@property (nonatomic, strong) id color;
#if TARGET_OS_IPHONE
@property (nonatomic, strong) IBInspectable UIColor *color;
#elif TARGET_OS_MAC
@property (nonatomic, strong) IBInspectable NSColor *color;
#endif
//------------------------------------------------------------------------------
/**
The plot's gain value, which controls the scale of the y-axis values. The default value of the gain is 1.0f and should always be greater than 0.0f.
*/
@property (nonatomic, assign) float gain;
@property (nonatomic, assign) IBInspectable float gain;
//------------------------------------------------------------------------------
@@ -92,14 +100,14 @@ typedef struct
/**
A BOOL indicating whether or not to fill in the graph. A value of YES will make a filled graph (filling in the space between the x-axis and the y-value), while a value of NO will create a stroked graph (connecting the points along the y-axis). Default is NO.
*/
@property (nonatomic, assign) BOOL shouldFill;
@property (nonatomic, assign) IBInspectable BOOL shouldFill;
//------------------------------------------------------------------------------
/**
A boolean indicating whether the graph should be rotated along the x-axis to give a mirrored reflection. This is typical for audio plots to produce the classic waveform look. A value of YES will produce a mirrored reflection of the y-values about the x-axis, while a value of NO will only plot the y-values. Default is NO.
*/
@property (nonatomic, assign) BOOL shouldMirror;
@property (nonatomic, assign) IBInspectable BOOL shouldMirror;
//------------------------------------------------------------------------------
#pragma mark - Updating The Plot
@@ -198,6 +206,28 @@ typedef struct
//------------------------------------------------------------------------------
/**
Called during the OpenGL run loop to constantly update the drawing 60 fps. Callers can use this force update the screen while subclasses can override this for complete control over their rendering. However, subclasses are more encouraged to use the `redrawWithPoints:pointCount:baseEffect:vertexBufferObject:vertexArrayBuffer:interpolated:mirrored:gain:`
*/
- (void)redraw;
//------------------------------------------------------------------------------
/**
Called after the view has been created. Subclasses should use to add any additional methods needed instead of overriding the init methods.
*/
- (void)setup;
//------------------------------------------------------------------------------
/**
Main method used to copy the sample data from the source buffer and update the
plot. Subclasses can overwrite this method for custom behavior.
@param data A float array of the sample data. Subclasses should copy this data to a separate array to avoid threading issues.
@param length The length of the float array as an int.
*/
- (void)setSampleData:(float *)data length:(int)length;
///-----------------------------------------------------------
/// @name Subclass Methods
///-----------------------------------------------------------
+18 -3
View File
@@ -182,6 +182,11 @@ typedef struct
self.color = [NSColor colorWithCalibratedRed:1.0f green:1.0f blue:1.0f alpha:1.0f];
#endif
//
// Allow subclass to initialize plot
//
[self setupPlot];
//
// Create the display link
//
@@ -191,6 +196,15 @@ typedef struct
//------------------------------------------------------------------------------
- (void)setupPlot
{
//
// Override in subclass
//
}
//------------------------------------------------------------------------------
- (void)setupOpenGL
{
self.baseEffect = [[GLKBaseEffect alloc] init];
@@ -247,6 +261,7 @@ typedef struct
#if !TARGET_OS_IPHONE
[self.openGLContext unlock];
#endif
self.frame = self.frame;
}
//------------------------------------------------------------------------------
@@ -258,9 +273,9 @@ typedef struct
//
// Update history
//
[EZAudioUtilities appendBuffer:buffer
withBufferSize:bufferSize
toHistoryInfo:self.info->historyInfo];
[EZAudioUtilities appendBufferRMS:buffer
withBufferSize:bufferSize
toHistoryInfo:self.info->historyInfo];
//
// Convert this data to point data
+19
View File
@@ -380,6 +380,13 @@ typedef NSRect EZRect;
*/
+ (float)SGN:(float)value;
//------------------------------------------------------------------------------
#pragma mark - Music Utilities
//------------------------------------------------------------------------------
+ (NSString *)noteNameStringForFrequency:(float)frequency
includeOctave:(BOOL)includeOctave;
//------------------------------------------------------------------------------
#pragma mark - OSStatus Utility
//------------------------------------------------------------------------------
@@ -494,6 +501,18 @@ typedef NSRect EZRect;
@param bufferSize A UInt32 representing the length of the incoming audio buffer
@param historyInfo A pointer to a EZPlotHistoryInfo structure to use for managing the history buffers
*/
+ (void)appendBufferRMS:(float *)buffer
withBufferSize:(UInt32)bufferSize
toHistoryInfo:(EZPlotHistoryInfo *)historyInfo;
//------------------------------------------------------------------------------
/**
Appends a buffer of audio data to the tail of a EZPlotHistoryInfo data structure. Thread-safe.
@param buffer A float array containing the incoming audio buffer to append to the history buffer
@param bufferSize A UInt32 representing the length of the incoming audio buffer
@param historyInfo A pointer to a EZPlotHistoryInfo structure to use for managing the history buffers
*/
+ (void)appendBuffer:(float *)buffer
withBufferSize:(UInt32)bufferSize
toHistoryInfo:(EZPlotHistoryInfo *)historyInfo;
+99 -22
View File
@@ -25,6 +25,22 @@
#import "EZAudioUtilities.h"
static float const EZAudioUtilitiesFixedNoteA = 440.0f;
static int const EZAudioUtilitiesFixedNoteAIndex = 9;
static int const EZAudioUtilitiesFixedNoteAOctave = 4;
static float const EZAudioUtilitiesEQFrequencyRatio = 1.059463094359f;
static int const EZAudioUtilitiesNotesLength = 12;
static NSString * const EZAudioUtilitiesNotes[EZAudioUtilitiesNotesLength] =
{
@"C", @"C#",
@"D", @"D#",
@"E",
@"F", @"F#",
@"G", @"G#",
@"A", @"A#",
@"B"
};
BOOL __shouldExitOnCheckResultFail = YES;
@implementation EZAudioUtilities
@@ -53,15 +69,29 @@ BOOL __shouldExitOnCheckResultFail = YES;
numberOfChannels:(UInt32)channels
interleaved:(BOOL)interleaved
{
AudioBufferList *audioBufferList = (AudioBufferList*)malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer) * (channels-1));
UInt32 outputBufferSize = 32 * frames; // 32 KB
audioBufferList->mNumberBuffers = interleaved ? 1 : channels;
for(int i = 0; i < audioBufferList->mNumberBuffers; i++)
unsigned nBuffers;
unsigned bufferSize;
unsigned channelsPerBuffer;
if (interleaved)
{
audioBufferList->mBuffers[i].mNumberChannels = channels;
audioBufferList->mBuffers[i].mDataByteSize = channels * outputBufferSize;
audioBufferList->mBuffers[i].mData = (float *)malloc(channels * sizeof(float) *outputBufferSize);
memset(audioBufferList->mBuffers[i].mData, 0, frames);
nBuffers = 1;
bufferSize = sizeof(float) * frames * channels;
channelsPerBuffer = channels;
}
else
{
nBuffers = channels;
bufferSize = sizeof(float) * frames;
channelsPerBuffer = 1;
}
AudioBufferList *audioBufferList = (AudioBufferList *)malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer) * (channels-1));
audioBufferList->mNumberBuffers = nBuffers;
for(unsigned i = 0; i < nBuffers; i++)
{
audioBufferList->mBuffers[i].mNumberChannels = channelsPerBuffer;
audioBufferList->mBuffers[i].mDataByteSize = bufferSize;
audioBufferList->mBuffers[i].mData = calloc(bufferSize, 1);
}
return audioBufferList;
}
@@ -106,6 +136,11 @@ BOOL __shouldExitOnCheckResultFail = YES;
+ (void)freeFloatBuffers:(float **)buffers numberOfChannels:(UInt32)channels
{
if (!buffers || !*buffers)
{
return;
}
for (int i = 0; i < channels; i++)
{
free(buffers[i]);
@@ -150,7 +185,7 @@ BOOL __shouldExitOnCheckResultFail = YES;
NULL,
&propSize,
&asbd)
operation:"Failed to fill out the rest of the m4a AudioStreamBasicDescription"];
operation:"Failed to fill out the rest of the iLBC AudioStreamBasicDescription"];
return asbd;
}
@@ -424,11 +459,11 @@ BOOL __shouldExitOnCheckResultFail = YES;
//------------------------------------------------------------------------------
+(float)MAP:(float)value
leftMin:(float)leftMin
leftMax:(float)leftMax
rightMin:(float)rightMin
rightMax:(float)rightMax
+ (float)MAP:(float)value
leftMin:(float)leftMin
leftMax:(float)leftMax
rightMin:(float)rightMin
rightMax:(float)rightMax
{
float leftSpan = leftMax - leftMin;
float rightSpan = rightMax - rightMin;
@@ -438,8 +473,7 @@ BOOL __shouldExitOnCheckResultFail = YES;
//------------------------------------------------------------------------------
+(float)RMS:(float *)buffer
length:(int)bufferSize
+ (float)RMS:(float *)buffer length:(int)bufferSize
{
float sum = 0.0;
for(int i = 0; i < bufferSize; i++)
@@ -449,11 +483,42 @@ BOOL __shouldExitOnCheckResultFail = YES;
//------------------------------------------------------------------------------
+(float)SGN:(float)value
+ (float)SGN:(float)value
{
return value < 0 ? -1.0f : ( value > 0 ? 1.0f : 0.0f);
}
//------------------------------------------------------------------------------
#pragma mark - Music Utilities
//------------------------------------------------------------------------------
+ (NSString *)noteNameStringForFrequency:(float)frequency
includeOctave:(BOOL)includeOctave
{
NSMutableString *noteName = [NSMutableString string];
int halfStepsFromFixedNote = roundf(log(frequency / EZAudioUtilitiesFixedNoteA) / log(EZAudioUtilitiesEQFrequencyRatio));
int halfStepsModOctaves = halfStepsFromFixedNote % EZAudioUtilitiesNotesLength;
int indexOfNote = EZAudioUtilitiesFixedNoteAIndex + halfStepsModOctaves;
float octaves = halfStepsFromFixedNote / EZAudioUtilitiesNotesLength;
if (indexOfNote >= EZAudioUtilitiesNotesLength)
{
indexOfNote -= EZAudioUtilitiesNotesLength;
octaves += 1;
}
else if (indexOfNote < 0)
{
indexOfNote += EZAudioUtilitiesNotesLength;
octaves = -1;
}
[noteName appendString:EZAudioUtilitiesNotes[indexOfNote]];
if (includeOctave)
{
int noteOctave = EZAudioUtilitiesFixedNoteAOctave + octaves;
[noteName appendFormat:@"%i", noteOctave];
}
return noteName;
}
//------------------------------------------------------------------------------
#pragma mark - OSStatus Utility
//------------------------------------------------------------------------------
@@ -590,6 +655,21 @@ BOOL __shouldExitOnCheckResultFail = YES;
#pragma mark - EZPlotHistoryInfo Utility
//------------------------------------------------------------------------------
+ (void)appendBufferRMS:(float *)buffer
withBufferSize:(UInt32)bufferSize
toHistoryInfo:(EZPlotHistoryInfo *)historyInfo
{
//
// Calculate RMS and append to buffer
//
float rms = [EZAudioUtilities RMS:buffer length:bufferSize];
float src[1];
src[0] = isnan(rms) ? 0.0 : rms;
[self appendBuffer:src withBufferSize:1 toHistoryInfo:historyInfo];
}
//------------------------------------------------------------------------------
+ (void)appendBuffer:(float *)buffer
withBufferSize:(UInt32)bufferSize
toHistoryInfo:(EZPlotHistoryInfo *)historyInfo
@@ -605,10 +685,7 @@ BOOL __shouldExitOnCheckResultFail = YES;
//
// Update the scroll history datasource
//
float rms = [EZAudioUtilities RMS:buffer length:bufferSize];
float src[1];
src[0] = isnan(rms) ? 0.0 : rms;
TPCircularBufferProduceBytes(&historyInfo->circularBuffer, src, sizeof(src));
TPCircularBufferProduceBytes(&historyInfo->circularBuffer, buffer, bufferSize * sizeof(float));
int32_t targetBytes = historyInfo->bufferSize * sizeof(float);
int32_t availableBytes = 0;
float *historyBuffer = TPCircularBufferTail(&historyInfo->circularBuffer, &availableBytes);
@@ -664,4 +741,4 @@ BOOL __shouldExitOnCheckResultFail = YES;
//------------------------------------------------------------------------------
@end
@end
+9
View File
@@ -54,6 +54,15 @@
/// @name Audio Data Description
///-----------------------------------------------------------
/**
Called anytime the EZMicrophone starts or stops.
@param output The instance of the EZMicrophone that triggered the event.
@param isPlaying A BOOL indicating whether the EZMicrophone instance is playing or not.
*/
- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying;
//------------------------------------------------------------------------------
/**
Called anytime the input device changes on an `EZMicrophone` instance.
@param microphone The instance of the EZMicrophone that triggered the event.
+27 -17
View File
@@ -70,7 +70,8 @@ static OSStatus EZAudioMicrophoneCallback(void *inRefCon,
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[EZAudioUtilities checkResult:AudioUnitUninitialize(self.info->audioUnit) operation:"Failed to unintialize audio unit for microphone"];
[EZAudioUtilities checkResult:AudioUnitUninitialize(self.info->audioUnit)
operation:"Failed to unintialize audio unit for microphone"];
[EZAudioUtilities freeBufferList:self.info->audioBufferList];
[EZAudioUtilities freeFloatBuffers:self.info->floatData
numberOfChannels:self.info->streamFormat.mChannelsPerFrame];
@@ -116,11 +117,7 @@ static OSStatus EZAudioMicrophoneCallback(void *inRefCon,
self = [self initWithMicrophoneDelegate:delegate];
if(self)
{
self.info = (EZMicrophoneInfo *)malloc(sizeof(EZMicrophoneInfo));
memset(self.info, 0, sizeof(EZMicrophoneInfo));
self.info->streamFormat = audioStreamBasicDescription;
_delegate = delegate;
[self setup];
[self setAudioStreamBasicDescription:audioStreamBasicDescription];
}
return self;
}
@@ -239,13 +236,8 @@ static OSStatus EZAudioMicrophoneCallback(void *inRefCon,
&flag,
sizeof(flag))
operation:"Couldn't enable input on remote IO unit."];
EZAudioDevice *currentInputDevice = [EZAudioDevice currentInputDevice];
[self setDevice:currentInputDevice];
#elif TARGET_OS_MAC
NSArray *inputDevices = [EZAudioDevice inputDevices];
EZAudioDevice *defaultMicrophone = [inputDevices lastObject];
[self setDevice:defaultMicrophone];
#endif
[self setDevice:[EZAudioDevice currentInputDevice]];
UInt32 propSize = sizeof(self.info->inputFormat);
[EZAudioUtilities checkResult:AudioUnitGetProperty(self.info->audioUnit,
@@ -260,11 +252,7 @@ static OSStatus EZAudioMicrophoneCallback(void *inRefCon,
NSAssert(self.info->inputFormat.mSampleRate, @"Expected AVAudioSession sample rate to be greater than 0.0. Did you setup the audio session?");
#elif TARGET_OS_MAC
#endif
if (self.info->streamFormat.mSampleRate == 0.0)
{
self.info->streamFormat = [self defaultStreamFormat];
}
[self setAudioStreamBasicDescription:self.info->streamFormat];
[self setAudioStreamBasicDescription:[self defaultStreamFormat]];
// render callback
AURenderCallbackStruct renderCallbackStruct;
@@ -349,16 +337,38 @@ static OSStatus EZAudioMicrophoneCallback(void *inRefCon,
-(void)startFetchingAudio
{
//
// Start output unit
//
[EZAudioUtilities checkResult:AudioOutputUnitStart(self.info->audioUnit)
operation:"Failed to start microphone audio unit"];
//
// Notify delegate
//
if ([self.delegate respondsToSelector:@selector(microphone:changedPlayingState:)])
{
[self.delegate microphone:self changedPlayingState:YES];
}
}
//------------------------------------------------------------------------------
-(void)stopFetchingAudio
{
//
// Stop output unit
//
[EZAudioUtilities checkResult:AudioOutputUnitStop(self.info->audioUnit)
operation:"Failed to stop microphone audio unit"];
//
// Notify delegate
//
if ([self.delegate respondsToSelector:@selector(microphone:changedPlayingState:)])
{
[self.delegate microphone:self changedPlayingState:NO];
}
}
//------------------------------------------------------------------------------
+5 -8
View File
@@ -108,8 +108,8 @@ OSStatus EZOutputGraphRenderCallback(void *inRefCon,
operation:"Failed to stop graph"];
[EZAudioUtilities checkResult:AUGraphClose(self.info->graph)
operation:"Failed to close graph"];
[EZAudioUtilities checkResult:AUGraphUninitialize(self.info->graph)
operation:"Failed to uninitialize graph"];
[EZAudioUtilities checkResult:DisposeAUGraph(self.info->graph)
operation:"Failed to dispose of graph"];
free(self.info);
}
@@ -314,14 +314,11 @@ OSStatus EZOutputGraphRenderCallback(void *inRefCon,
[self setClientFormat:[self defaultClientFormat]];
[self setInputFormat:[self defaultInputFormat]];
#if TARGET_OS_IPHONE
//
// Use the default device
//
EZAudioDevice *currentOutputDevice = [EZAudioDevice currentOutputDevice];
[self setDevice:currentOutputDevice];
#elif TARGET_OS_MAC
NSArray *outputDevices = [EZAudioDevice outputDevices];
EZAudioDevice *defaultOutput = [outputDevices firstObject];
[self setDevice:defaultOutput];
#endif
//
// Set maximum frames per slice to 4096 to allow playback during
+15 -8
View File
@@ -75,32 +75,40 @@ typedef NS_ENUM(NSInteger, EZPlotType)
/**
The default background color of the plot. For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is black.
*/
@property (nonatomic,strong) id backgroundColor;
#if TARGET_OS_IPHONE
@property (nonatomic, strong) IBInspectable UIColor *backgroundColor;
#elif TARGET_OS_MAC
@property (nonatomic, strong) IBInspectable NSColor *backgroundColor;
#endif
/**
The default color of the plot's data (i.e. waveform, y-axis values). For iOS the color is specified as a UIColor while for OSX the color is an NSColor. The default value on both platforms is red.
*/
@property (nonatomic,strong) id color;
#if TARGET_OS_IPHONE
@property (nonatomic, strong) IBInspectable UIColor *color;
#elif TARGET_OS_MAC
@property (nonatomic, strong) IBInspectable NSColor *color;
#endif
/**
The plot's gain value, which controls the scale of the y-axis values. The default value of the gain is 1.0f and should always be greater than 0.0f.
*/
@property (nonatomic,assign,setter=setGain:) float gain;
@property (nonatomic, assign) IBInspectable float gain;
/**
The type of plot as specified by the `EZPlotType` enumeration (i.e. a buffer or rolling plot type).
*/
@property (nonatomic,assign,setter=setPlotType:) EZPlotType plotType;
@property (nonatomic, assign) IBInspectable EZPlotType plotType;
/**
A boolean indicating whether or not to fill in the graph. A value of YES will make a filled graph (filling in the space between the x-axis and the y-value), while a value of NO will create a stroked graph (connecting the points along the y-axis).
*/
@property (nonatomic,assign,setter=setShouldFill:) BOOL shouldFill;
@property (nonatomic, assign) IBInspectable BOOL shouldFill;
/**
A boolean indicating whether the graph should be rotated along the x-axis to give a mirrored reflection. This is typical for audio plots to produce the classic waveform look. A value of YES will produce a mirrored reflection of the y-values about the x-axis, while a value of NO will only plot the y-values.
*/
@property (nonatomic,assign,setter=setShouldMirror:) BOOL shouldMirror;
@property (nonatomic, assign) IBInspectable BOOL shouldMirror;
//------------------------------------------------------------------------------
#pragma mark - Clearing
@@ -129,7 +137,6 @@ typedef NS_ENUM(NSInteger, EZPlotType)
@param bufferSize The size of the float array that will be mapped to the y-axis.
@warning The bufferSize is expected to be the same, constant value once initial triggered. For plots using OpenGL a vertex buffer object will be allocated with a maximum buffersize of (2 * the initial given buffer size) to account for any interpolation necessary for filling in the graph. Updates use the glBufferSubData(...) function, which will crash if the buffersize exceeds the initial maximum allocated size.
*/
-(void)updateBuffer:(float *)buffer
withBufferSize:(UInt32)bufferSize;
-(void)updateBuffer:(float *)buffer withBufferSize:(UInt32)bufferSize;
@end
+257 -16
View File
@@ -26,6 +26,12 @@
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
@class EZRecorder;
//------------------------------------------------------------------------------
#pragma mark - Data Structures
//------------------------------------------------------------------------------
/**
To ensure valid recording formats are used when recording to a file the EZRecorderFileType describes the most common file types that a file can be encoded in. Each of these types can be used to output recordings as such:
@@ -50,57 +56,290 @@ typedef NS_ENUM(NSInteger, EZRecorderFileType)
EZRecorderFileTypeWAV
};
//------------------------------------------------------------------------------
#pragma mark - EZRecorderDelegate
//------------------------------------------------------------------------------
/**
The EZRecorderDelegate for the EZRecorder provides a receiver for write events, `recorderUpdatedCurrentTime:`, and the close event, `recorderDidClose:`.
*/
@protocol EZRecorderDelegate <NSObject>
@optional
/**
Triggers when the EZRecorder is explicitly closed with the `closeAudioFile` method.
@param recorder The EZRecorder instance that triggered the action
*/
- (void)recorderDidClose:(EZRecorder *)recorder;
/**
Triggers after the EZRecorder has successfully written audio data from the `appendDataFromBufferList:withBufferSize:` method.
@param recorder The EZRecorder instance that triggered the action
*/
- (void)recorderUpdatedCurrentTime:(EZRecorder *)recorder;
@end
//------------------------------------------------------------------------------
#pragma mark - EZRecorder
//------------------------------------------------------------------------------
/**
The EZRecorder provides a flexible way to create an audio file and append raw audio data to it. The EZRecorder will convert the incoming audio on the fly to the destination format so no conversion is needed between this and any other component. Right now the only supported output format is 'caf'. Each output file should have its own EZRecorder instance (think 1 EZRecorder = 1 audio file).
*/
@interface EZRecorder : NSObject
//------------------------------------------------------------------------------
#pragma mark - Properties
//------------------------------------------------------------------------------
/**
An EZRecorderDelegate to listen for the write and close events.
*/
@property (nonatomic, weak) id<EZRecorderDelegate> delegate;
//------------------------------------------------------------------------------
#pragma mark - Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Initializers
///-----------------------------------------------------------
/**
Creates an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), and a file type (see `EZRecorderFileType`) that will automatically create an internal `fileFormat` and audio file type hint.
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileType A constant described by the EZRecorderFileType that corresponds to the type of destination file that should be written. For instance, an AAC file written using an '.m4a' extension would correspond to EZRecorderFileTypeM4A. See EZRecorderFileType for all the constants and mapping combinations.
@return A newly created EZRecorder instance.
*/
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), and a file type (see `EZRecorderFileType`) that will automatically create an internal `fileFormat` and audio file type hint, as well as a delegate to respond to the recorder's write and close events.
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileType A constant described by the EZRecorderFileType that corresponds to the type of destination file that should be written. For instance, an AAC file written using an '.m4a' extension would correspond to EZRecorderFileTypeM4A. See EZRecorderFileType for all the constants and mapping combinations.
@param delegate An EZRecorderDelegate to listen for the recorder's write and close events.
@return A newly created EZRecorder instance.
*/
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType
delegate:(id<EZRecorderDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), a file format describing the destination format on disk (see `fileFormat` for more info), and an audio file type (an AudioFileTypeID for Core Audio, not a EZRecorderFileType).
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileFormat An AudioStreamBasicDescription describing the format of the audio being written to disk (MP3, AAC, WAV, etc)
@param audioFileTypeID An AudioFileTypeID that matches your fileFormat (i.e. kAudioFileM4AType for an M4A format)
@return A newly created EZRecorder instance.
*/
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), a file format describing the destination format on disk (see `fileFormat` for more info), an audio file type (an AudioFileTypeID for Core Audio, not a EZRecorderFileType), and delegate to respond to the recorder's write and close events.
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileFormat An AudioStreamBasicDescription describing the format of the audio being written to disk (MP3, AAC, WAV, etc)
@param audioFileTypeID An AudioFileTypeID that matches your fileFormat (i.e. kAudioFileM4AType for an M4A format)
@param delegate An EZRecorderDelegate to listen for the recorder's write and close events.
@return A newly created EZRecorder instance.
*/
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID
delegate:(id<EZRecorderDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Creates a new instance of an EZRecorder using a destination file path URL and the source format of the incoming audio.
@param url An NSURL specifying the file path location of where the audio file should be written to.
@param sourceFormat The AudioStreamBasicDescription for the incoming audio that will be written to the file.
@param destinationFileType A constant described by the EZRecorderFileType that corresponds to the type of destination file that should be written. For instance, an AAC file written using an '.m4a' extension would correspond to EZRecorderFileTypeM4A. See EZRecorderFileType for all the constants and mapping combinations.
@deprecated This property is deprecated starting in version 0.8.0.
@note Please use `initWithURL:clientFormat:fileType:` initializer instead.
@return The newly created EZRecorder instance.
*/
-(EZRecorder*)initWithDestinationURL:(NSURL*)url
- (instancetype)initWithDestinationURL:(NSURL*)url
sourceFormat:(AudioStreamBasicDescription)sourceFormat
destinationFileType:(EZRecorderFileType)destinationFileType;
destinationFileType:(EZRecorderFileType)destinationFileType __attribute__((deprecated));
//------------------------------------------------------------------------------
#pragma mark - Class Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Class Initializers
///-----------------------------------------------------------
/**
Class method to create an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), and a file type (see `EZRecorderFileType`) that will automatically create an internal `fileFormat` and audio file type hint.
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileType A constant described by the EZRecorderFileType that corresponds to the type of destination file that should be written. For instance, an AAC file written using an '.m4a' extension would correspond to EZRecorderFileTypeM4A. See EZRecorderFileType for all the constants and mapping combinations.
@return A newly created EZRecorder instance.
*/
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType;
//------------------------------------------------------------------------------
/**
Class method to create an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), and a file type (see `EZRecorderFileType`) that will automatically create an internal `fileFormat` and audio file type hint, as well as a delegate to respond to the recorder's write and close events.
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileType A constant described by the EZRecorderFileType that corresponds to the type of destination file that should be written. For instance, an AAC file written using an '.m4a' extension would correspond to EZRecorderFileTypeM4A. See EZRecorderFileType for all the constants and mapping combinations.
@param delegate An EZRecorderDelegate to listen for the recorder's write and close events.
@return A newly created EZRecorder instance.
*/
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType
delegate:(id<EZRecorderDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Class method to create an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), a file format describing the destination format on disk (see `fileFormat` for more info), and an audio file type (an AudioFileTypeID for Core Audio, not a EZRecorderFileType).
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileFormat An AudioStreamBasicDescription describing the format of the audio being written to disk (MP3, AAC, WAV, etc)
@param audioFileTypeID An AudioFileTypeID that matches your fileFormat (i.e. kAudioFileM4AType for an M4A format)
@return A newly created EZRecorder instance.
*/
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID;
//------------------------------------------------------------------------------
/**
Class method to create an instance of the EZRecorder with a file path URL to write out the file to, a client format describing the in-application common format (see `clientFormat` for more info), a file format describing the destination format on disk (see `fileFormat` for more info), an audio file type (an AudioFileTypeID for Core Audio, not a EZRecorderFileType), and delegate to respond to the recorder's write and close events.
@param url An NSURL representing the file path the output file should be written
@param clientFormat An AudioStreamBasicDescription describing the in-applciation common format (always linear PCM)
@param fileFormat An AudioStreamBasicDescription describing the format of the audio being written to disk (MP3, AAC, WAV, etc)
@param audioFileTypeID An AudioFileTypeID that matches your fileFormat (i.e. kAudioFileM4AType for an M4A format)
@param delegate An EZRecorderDelegate to listen for the recorder's write and close events.
@return A newly created EZRecorder instance.
*/
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID
delegate:(id<EZRecorderDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Class method to create a new instance of an EZRecorder using a destination file path URL and the source format of the incoming audio.
@param url An NSURL specifying the file path location of where the audio file should be written to.
@param sourceFormat The AudioStreamBasicDescription for the incoming audio that will be written to the file.
@param sourceFormat The AudioStreamBasicDescription for the incoming audio that will be written to the file (also called the `clientFormat`).
@param destinationFileType A constant described by the EZRecorderFileType that corresponds to the type of destination file that should be written. For instance, an AAC file written using an '.m4a' extension would correspond to EZRecorderFileTypeM4A. See EZRecorderFileType for all the constants and mapping combinations.
@return The newly created EZRecorder instance.
*/
+(EZRecorder*)recorderWithDestinationURL:(NSURL*)url
sourceFormat:(AudioStreamBasicDescription)sourceFormat
destinationFileType:(EZRecorderFileType)destinationFileType;
+ (instancetype)recorderWithDestinationURL:(NSURL*)url
sourceFormat:(AudioStreamBasicDescription)sourceFormat
destinationFileType:(EZRecorderFileType)destinationFileType __attribute__((deprecated));
//------------------------------------------------------------------------------
#pragma mark - Properties
//------------------------------------------------------------------------------
#pragma mark - Getters
///-----------------------------------------------------------
/// @name Getting The Recorder's Properties
///-----------------------------------------------------------
/**
Provides the common AudioStreamBasicDescription that will be used for in-app interaction. The recorder's format will be converted from this format to the `fileFormat`. For instance, the file on disk could be a 22.5 kHz, float format, but we might have an audio processing graph that has a 44.1 kHz, signed integer format that we'd like to interact with. The client format lets us set that 44.1 kHz format on the recorder to properly write samples from the graph out to the file in the desired destination format.
@warning This must be a linear PCM format!
@return An AudioStreamBasicDescription structure describing the format of the audio file.
*/
@property (readwrite) AudioStreamBasicDescription clientFormat;
//------------------------------------------------------------------------------
/**
Provides the current write offset in the audio file as an NSTimeInterval (i.e. in seconds). When setting this it will determine the correct frame offset and perform a `seekToFrame` to the new time offset.
@warning Make sure the new current time offset is less than the `duration` or you will receive an invalid seek assertion.
*/
@property (readonly) NSTimeInterval currentTime;
//------------------------------------------------------------------------------
/**
Provides the duration of the audio file in seconds.
*/
@property (readonly) NSTimeInterval duration;
//------------------------------------------------------------------------------
/**
Provides the AudioStreamBasicDescription structure containing the format of the recorder's audio file.
@return An AudioStreamBasicDescription structure describing the format of the audio file.
*/
@property (readonly) AudioStreamBasicDescription fileFormat;
//------------------------------------------------------------------------------
/**
Provides the current time as an NSString with the time format MM:SS.
*/
@property (readonly) NSString *formattedCurrentTime;
//------------------------------------------------------------------------------
/**
Provides the duration as an NSString with the time format MM:SS.
*/
@property (readonly) NSString *formattedDuration;
//------------------------------------------------------------------------------
/**
Provides the frame index (a.k.a the write positon) within the audio file as SInt64. This can be helpful when seeking through the audio file.
@return The current frame index within the audio file as a SInt64.
*/
@property (readonly) SInt64 frameIndex;
//------------------------------------------------------------------------------
/**
Provides the total frame count of the recorder's audio file in the file format.
@return The total number of frames in the recorder in the AudioStreamBasicDescription representing the file format as a SInt64.
*/
@property (readonly) SInt64 totalFrames;
//------------------------------------------------------------------------------
/**
Provides the file path that's currently being used by the recorder.
@return The NSURL representing the file path of the audio file path being used for recording.
@return The NSURL representing the file path of the recorder path being used for recording.
*/
-(NSURL*)url;
- (NSURL *)url;
//------------------------------------------------------------------------------
#pragma mark - Events
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Appending Data To The Audio File
/// @name Appending Data To The Recorder
///-----------------------------------------------------------
/**
@@ -108,16 +347,18 @@ typedef NS_ENUM(NSInteger, EZRecorderFileType)
@param bufferList The AudioBufferList holding the audio data to append
@param bufferSize The size of each of the buffers in the buffer list.
*/
-(void)appendDataFromBufferList:(AudioBufferList*)bufferList
withBufferSize:(UInt32)bufferSize;
- (void)appendDataFromBufferList:(AudioBufferList *)bufferList
withBufferSize:(UInt32)bufferSize;
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Closing The Audio File
/// @name Closing The Recorder
///-----------------------------------------------------------
/**
Finishes writes to the audio file and closes it.
Finishes writes to the recorder's audio file and closes it.
*/
-(void)closeAudioFile;
- (void)closeAudioFile;
@end
+327 -63
View File
@@ -26,57 +26,202 @@
#import "EZRecorder.h"
#import "EZAudioUtilities.h"
@interface EZRecorder (){
ExtAudioFileRef _destinationFile;
AudioFileTypeID _destinationFileTypeID;
CFURLRef _destinationFileURL;
AudioStreamBasicDescription _destinationFormat;
AudioStreamBasicDescription _sourceFormat;
}
//------------------------------------------------------------------------------
#pragma mark - Data Structures
//------------------------------------------------------------------------------
typedef struct
{
AudioFileTypeID audioFileTypeID;
ExtAudioFileRef extAudioFileRef;
AudioStreamBasicDescription clientFormat;
BOOL closed;
CFURLRef fileURL;
AudioStreamBasicDescription fileFormat;
} EZRecorderInfo;
//------------------------------------------------------------------------------
#pragma mark - EZRecorder (Interface Extension)
//------------------------------------------------------------------------------
@interface EZRecorder ()
@property (nonatomic, assign) EZRecorderInfo *info;
@end
//------------------------------------------------------------------------------
#pragma mark - EZRecorder (Implementation)
//------------------------------------------------------------------------------
@implementation EZRecorder
#pragma mark - Initializers
-(EZRecorder*)initWithDestinationURL:(NSURL*)url
sourceFormat:(AudioStreamBasicDescription)sourceFormat
destinationFileType:(EZRecorderFileType)destinationFileType
//------------------------------------------------------------------------------
#pragma mark - Dealloc
//------------------------------------------------------------------------------
- (void)dealloc
{
if (!self.info->closed)
{
[self closeAudioFile];
}
free(self.info);
}
//------------------------------------------------------------------------------
#pragma mark - Initializers
//------------------------------------------------------------------------------
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType
{
return [self initWithURL:url
clientFormat:clientFormat
fileType:fileType
delegate:nil];
}
//------------------------------------------------------------------------------
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType
delegate:(id<EZRecorderDelegate>)delegate
{
AudioStreamBasicDescription fileFormat = [EZRecorder formatForFileType:fileType
withSourceFormat:clientFormat];
AudioFileTypeID audioFileTypeID = [EZRecorder fileTypeIdForFileType:fileType
withSourceFormat:clientFormat];
return [self initWithURL:url
clientFormat:clientFormat
fileFormat:fileFormat
audioFileTypeID:audioFileTypeID
delegate:delegate];
}
//------------------------------------------------------------------------------
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID
{
return [self initWithURL:url
clientFormat:clientFormat
fileFormat:fileFormat
audioFileTypeID:audioFileTypeID
delegate:nil];
}
//------------------------------------------------------------------------------
- (instancetype)initWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID
delegate:(id<EZRecorderDelegate>)delegate
{
self = [super init];
if (self)
{
// Set defaults
_destinationFile = NULL;
_destinationFileURL = (__bridge CFURLRef)url;
_sourceFormat = sourceFormat;
_destinationFormat = [EZRecorder recorderFormatForFileType:destinationFileType
withSourceFormat:_sourceFormat];
_destinationFileTypeID = [EZRecorder recorderFileTypeIdForFileType:destinationFileType
withSourceFormat:_sourceFormat];
// Initializer the recorder instance
[self _initializeRecorder];
self.info = (EZRecorderInfo *)calloc(1, sizeof(EZRecorderInfo));
self.info->audioFileTypeID = audioFileTypeID;
self.info->fileURL = (__bridge CFURLRef)url;
self.info->clientFormat = clientFormat;
self.info->fileFormat = fileFormat;
self.delegate = delegate;
[self setup];
}
return self;
}
//------------------------------------------------------------------------------
- (instancetype)initWithDestinationURL:(NSURL*)url
sourceFormat:(AudioStreamBasicDescription)sourceFormat
destinationFileType:(EZRecorderFileType)destinationFileType
{
return [self initWithURL:url
clientFormat:sourceFormat
fileType:destinationFileType];
}
//------------------------------------------------------------------------------
#pragma mark - Class Initializers
+(EZRecorder*)recorderWithDestinationURL:(NSURL*)url
sourceFormat:(AudioStreamBasicDescription)sourceFormat
destinationFileType:(EZRecorderFileType)destinationFileType
//------------------------------------------------------------------------------
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType
{
return [[self alloc] initWithURL:url
clientFormat:clientFormat
fileType:fileType];
}
//------------------------------------------------------------------------------
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileType:(EZRecorderFileType)fileType
delegate:(id<EZRecorderDelegate>)delegate
{
return [[self alloc] initWithURL:url
clientFormat:clientFormat
fileType:fileType
delegate:delegate];
}
//------------------------------------------------------------------------------
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID
{
return [[self alloc] initWithURL:url
clientFormat:clientFormat
fileFormat:fileFormat
audioFileTypeID:audioFileTypeID];
}
//------------------------------------------------------------------------------
+ (instancetype)recorderWithURL:(NSURL *)url
clientFormat:(AudioStreamBasicDescription)clientFormat
fileFormat:(AudioStreamBasicDescription)fileFormat
audioFileTypeID:(AudioFileTypeID)audioFileTypeID
delegate:(id<EZRecorderDelegate>)delegate
{
return [[self alloc] initWithURL:url
clientFormat:clientFormat
fileFormat:fileFormat
audioFileTypeID:audioFileTypeID
delegate:delegate];
}
//------------------------------------------------------------------------------
+ (instancetype)recorderWithDestinationURL:(NSURL*)url
sourceFormat:(AudioStreamBasicDescription)sourceFormat
destinationFileType:(EZRecorderFileType)destinationFileType
{
return [[EZRecorder alloc] initWithDestinationURL:url
sourceFormat:sourceFormat
destinationFileType:destinationFileType];
}
#pragma mark - Private Configuration
+(AudioStreamBasicDescription)recorderFormatForFileType:(EZRecorderFileType)fileType
withSourceFormat:(AudioStreamBasicDescription)sourceFormat
//------------------------------------------------------------------------------
#pragma mark - Class Methods
//------------------------------------------------------------------------------
+ (AudioStreamBasicDescription)formatForFileType:(EZRecorderFileType)fileType
withSourceFormat:(AudioStreamBasicDescription)sourceFormat
{
AudioStreamBasicDescription asbd;
switch ( fileType)
switch (fileType)
{
case EZRecorderFileTypeAIFF:
asbd = [EZAudioUtilities AIFFFormatWithNumberOfChannels:sourceFormat.mChannelsPerFrame
@@ -98,11 +243,13 @@
return asbd;
}
+(AudioFileTypeID)recorderFileTypeIdForFileType:(EZRecorderFileType)fileType
withSourceFormat:(AudioStreamBasicDescription)sourceFormat
//------------------------------------------------------------------------------
+ (AudioFileTypeID)fileTypeIdForFileType:(EZRecorderFileType)fileType
withSourceFormat:(AudioStreamBasicDescription)sourceFormat
{
AudioFileTypeID audioFileTypeID;
switch ( fileType)
switch (fileType)
{
case EZRecorderFileTypeAIFF:
audioFileTypeID = kAudioFileAIFFType;
@@ -123,70 +270,187 @@
return audioFileTypeID;
}
-(void)_initializeRecorder
//------------------------------------------------------------------------------
- (void)setup
{
// Finish filling out the destination format description
UInt32 propSize = sizeof(_destinationFormat);
UInt32 propSize = sizeof(self.info->fileFormat);
[EZAudioUtilities checkResult:AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
0,
NULL,
&propSize,
&_destinationFormat)
&self.info->fileFormat)
operation:"Failed to fill out rest of destination format"];
//
// Create the audio file
[EZAudioUtilities checkResult:ExtAudioFileCreateWithURL(_destinationFileURL,
_destinationFileTypeID,
&_destinationFormat,
//
[EZAudioUtilities checkResult:ExtAudioFileCreateWithURL(self.info->fileURL,
self.info->audioFileTypeID,
&self.info->fileFormat,
NULL,
kAudioFileFlags_EraseFile,
&_destinationFile)
&self.info->extAudioFileRef)
operation:"Failed to create audio file"];
// Set the client format (which should be equal to the source format)
[EZAudioUtilities checkResult:ExtAudioFileSetProperty(_destinationFile,
kExtAudioFileProperty_ClientDataFormat,
sizeof(_sourceFormat),
&_sourceFormat)
operation:"Failed to set client format on recorded audio file"];
//
// Set the client format
//
[self setClientFormat:self.info->clientFormat];
}
//------------------------------------------------------------------------------
#pragma mark - Events
-(void)appendDataFromBufferList:(AudioBufferList *)bufferList
withBufferSize:(UInt32)bufferSize
//------------------------------------------------------------------------------
- (void)appendDataFromBufferList:(AudioBufferList *)bufferList
withBufferSize:(UInt32)bufferSize
{
if (_destinationFile)
//
// Make sure the audio file is not closed
//
NSAssert(!self.info->closed, @"Cannot append data when EZRecorder has been closed. You must create a new instance.;");
//
// Perform the write
//
[EZAudioUtilities checkResult:ExtAudioFileWrite(self.info->extAudioFileRef,
bufferSize,
bufferList)
operation:"Failed to write audio data to recorded audio file"];
//
// Notify delegate
//
if ([self.delegate respondsToSelector:@selector(recorderUpdatedCurrentTime:)])
{
[EZAudioUtilities checkResult:ExtAudioFileWriteAsync(_destinationFile,
bufferSize,
bufferList)
operation:"Failed to write audio data to recorded audio file"];
[self.delegate recorderUpdatedCurrentTime:self];
}
}
-(void)closeAudioFile
//------------------------------------------------------------------------------
- (void)closeAudioFile
{
if (_destinationFile)
if (!self.info->closed)
{
// Dispose of the audio file reference
[EZAudioUtilities checkResult:ExtAudioFileDispose(_destinationFile)
//
// Close, audio file can no longer be written to
//
[EZAudioUtilities checkResult:ExtAudioFileDispose(self.info->extAudioFileRef)
operation:"Failed to close audio file"];
self.info->closed = YES;
// Null out the file reference
_destinationFile = NULL;
//
// Notify delegate
//
if ([self.delegate respondsToSelector:@selector(recorderDidClose:)])
{
[self.delegate recorderDidClose:self];
}
}
}
-(NSURL *)url
//------------------------------------------------------------------------------
#pragma mark - Getters
//------------------------------------------------------------------------------
- (AudioStreamBasicDescription)clientFormat
{
return (__bridge NSURL*)_destinationFileURL;
return self.info->clientFormat;
}
#pragma mark - Dealloc
-(void)dealloc
//-----------------------------------------------------------------------------
- (NSTimeInterval)currentTime
{
[self closeAudioFile];
NSTimeInterval currentTime = 0.0;
NSTimeInterval duration = [self duration];
if (duration != 0.0)
{
currentTime = (NSTimeInterval)[EZAudioUtilities MAP:(float)[self frameIndex]
leftMin:0.0f
leftMax:(float)[self totalFrames]
rightMin:0.0f
rightMax:duration];
}
return currentTime;
}
//------------------------------------------------------------------------------
- (NSTimeInterval)duration
{
NSTimeInterval frames = (NSTimeInterval)[self totalFrames];
return (NSTimeInterval) frames / self.info->fileFormat.mSampleRate;
}
//------------------------------------------------------------------------------
- (AudioStreamBasicDescription)fileFormat
{
return self.info->fileFormat;
}
//------------------------------------------------------------------------------
- (NSString *)formattedCurrentTime
{
return [EZAudioUtilities displayTimeStringFromSeconds:[self currentTime]];
}
//------------------------------------------------------------------------------
- (NSString *)formattedDuration
{
return [EZAudioUtilities displayTimeStringFromSeconds:[self duration]];
}
//------------------------------------------------------------------------------
- (SInt64)frameIndex
{
SInt64 frameIndex;
[EZAudioUtilities checkResult:ExtAudioFileTell(self.info->extAudioFileRef,
&frameIndex)
operation:"Failed to get frame index"];
return frameIndex;
}
//------------------------------------------------------------------------------
- (SInt64)totalFrames
{
SInt64 totalFrames;
UInt32 propSize = sizeof(SInt64);
[EZAudioUtilities checkResult:ExtAudioFileGetProperty(self.info->extAudioFileRef,
kExtAudioFileProperty_FileLengthFrames,
&propSize,
&totalFrames)
operation:"Recorder failed to get total frames."];
return totalFrames;
}
//------------------------------------------------------------------------------
- (NSURL *)url
{
return (__bridge NSURL*)self.info->fileURL;
}
//------------------------------------------------------------------------------
#pragma mark - Setters
//------------------------------------------------------------------------------
- (void)setClientFormat:(AudioStreamBasicDescription)clientFormat
{
[EZAudioUtilities checkResult:ExtAudioFileSetProperty(self.info->extAudioFileRef,
kExtAudioFileProperty_ClientDataFormat,
sizeof(clientFormat),
&clientFormat)
operation:"Failed to set client format on recorded audio file"];
self.info->clientFormat = clientFormat;
}
@end
@@ -38,6 +38,8 @@
66755A401B3B790D0013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 66755A2B1B3B790D0013E67E /* TPCircularBuffer.c */; };
66755A411B3B790D0013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 66755A2E1B3B790D0013E67E /* CHANGELOG */; };
66755A421B3B790D0013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 66755A2F1B3B790D0013E67E /* VERSION */; };
667EEA541B51EF9400D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA531B51EF9400D57FB2 /* EZAudioFFT.m */; };
667EEA681B51F0C000D57FB2 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 667EEA671B51F0C000D57FB2 /* Accelerate.framework */; };
94056D88185B97E300EB94BA /* CoreGraphicsWaveformViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94056D86185B97E300EB94BA /* CoreGraphicsWaveformViewController.m */; };
94056D89185B97E300EB94BA /* CoreGraphicsWaveformViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 94056D87185B97E300EB94BA /* CoreGraphicsWaveformViewController.xib */; };
94373025185B931C00F315F0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94373024185B931C00F315F0 /* Cocoa.framework */; };
@@ -102,6 +104,9 @@
66755A2C1B3B790D0013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
66755A2E1B3B790D0013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
66755A2F1B3B790D0013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA521B51EF9400D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA531B51EF9400D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
667EEA671B51F0C000D57FB2 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
94056D85185B97E300EB94BA /* CoreGraphicsWaveformViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CoreGraphicsWaveformViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
94056D86185B97E300EB94BA /* CoreGraphicsWaveformViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = CoreGraphicsWaveformViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
94056D87185B97E300EB94BA /* CoreGraphicsWaveformViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CoreGraphicsWaveformViewController.xib; sourceTree = "<group>"; };
@@ -137,6 +142,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
667EEA681B51F0C000D57FB2 /* Accelerate.framework in Frameworks */,
94373088185B937E00F315F0 /* QuartzCore.framework in Frameworks */,
94373086185B937100F315F0 /* OpenGL.framework in Frameworks */,
94373084185B936B00F315F0 /* GLKit.framework in Frameworks */,
@@ -168,6 +174,8 @@
66755A101B3B790D0013E67E /* EZAudioDevice.m */,
66755A111B3B790D0013E67E /* EZAudioDisplayLink.h */,
66755A121B3B790D0013E67E /* EZAudioDisplayLink.m */,
667EEA521B51EF9400D57FB2 /* EZAudioFFT.h */,
667EEA531B51EF9400D57FB2 /* EZAudioFFT.m */,
66755A131B3B790D0013E67E /* EZAudioFile.h */,
66755A141B3B790D0013E67E /* EZAudioFile.m */,
66755A151B3B790D0013E67E /* EZAudioFloatConverter.h */,
@@ -229,6 +237,7 @@
94373023185B931C00F315F0 /* Frameworks */ = {
isa = PBXGroup;
children = (
667EEA671B51F0C000D57FB2 /* Accelerate.framework */,
94373087185B937E00F315F0 /* QuartzCore.framework */,
94373085185B937100F315F0 /* OpenGL.framework */,
94373083185B936B00F315F0 /* GLKit.framework */,
@@ -420,6 +429,7 @@
66755A371B3B790D0013E67E /* EZAudioPlayer.m in Sources */,
94056D88185B97E300EB94BA /* CoreGraphicsWaveformViewController.m in Sources */,
66755A391B3B790D0013E67E /* EZAudioPlotGL.m in Sources */,
667EEA541B51EF9400D57FB2 /* EZAudioFFT.m in Sources */,
66755A341B3B790D0013E67E /* EZAudioFile.m in Sources */,
66755A3D1B3B790D0013E67E /* EZOutput.m in Sources */,
66755A3B1B3B790D0013E67E /* EZAudioUtilities.m in Sources */,
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@@ -648,7 +648,8 @@
</items>
</menu>
<window title="EZAudioCoreGraphicsWaveformExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="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="877"/>
@@ -57,6 +57,11 @@
*/
@property (nonatomic, weak) IBOutlet NSPopUpButton *microphoneInputChannelPopUpButton;
/**
The checkbox button used to turn the microphone off/on
*/
@property (nonatomic, weak) IBOutlet NSButton *microphoneSwitch;
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
@@ -240,4 +240,25 @@ withNumberOfChannels:(UInt32)numberOfChannels
//------------------------------------------------------------------------------
- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying
{
NSString *title = isPlaying ? @"Microphone On" : @"Microphone Off";
[self setTitle:title forButton:self.microphoneSwitch];
}
//------------------------------------------------------------------------------
#pragma mark - Utility
//------------------------------------------------------------------------------
- (void)setTitle:(NSString *)title forButton:(NSButton *)button
{
NSDictionary *attributes = @{ NSForegroundColorAttributeName : [NSColor whiteColor] };
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title
attributes:attributes];
button.attributedTitle = attributedTitle;
button.attributedAlternateTitle = attributedTitle;
}
//------------------------------------------------------------------------------
@end
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment version="1070" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="CoreGraphicsWaveformViewController">
@@ -10,6 +10,7 @@
<outlet property="audioPlot" destination="wpL-Ou-GSb" id="OME-Hf-I27"/>
<outlet property="microphoneInputChannelPopUpButton" destination="Yi6-fS-Cob" id="pLg-4c-klV"/>
<outlet property="microphoneInputPopUpButton" destination="SjR-qx-mWV" id="NuN-SS-ESg"/>
<outlet property="microphoneSwitch" destination="kAI-gs-c31" id="ADZ-Fg-aCN"/>
<outlet property="view" destination="wpL-Ou-GSb" id="oxJ-iT-SKO"/>
</connections>
</customObject>
@@ -83,7 +84,7 @@
<rect key="frame" x="18" y="43" width="36" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Input" id="Png-Pk-fMc">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
@@ -91,7 +92,7 @@
<rect key="frame" x="204" y="43" width="55" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Channel" id="lkh-zp-WCY">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
@@ -111,7 +112,7 @@
<constraint firstItem="SjR-qx-mWV" firstAttribute="top" secondItem="fi6-Uh-bvr" secondAttribute="bottom" constant="5" id="qkS-wp-O0d"/>
<constraint firstAttribute="trailing" secondItem="HTa-6n-EPo" secondAttribute="trailing" constant="20" id="rGZ-5W-ZDN"/>
</constraints>
<point key="canvasLocation" x="178" y="314"/>
<point key="canvasLocation" x="226" y="324"/>
</customView>
</objects>
</document>
@@ -24,6 +24,7 @@
66755B961B3B79380013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 66755B811B3B79380013E67E /* TPCircularBuffer.c */; };
66755B971B3B79380013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 66755B841B3B79380013E67E /* CHANGELOG */; };
66755B981B3B79380013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 66755B851B3B79380013E67E /* VERSION */; };
667EEA661B51EFDB00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA651B51EFDB00D57FB2 /* EZAudioFFT.m */; };
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 */; };
@@ -89,6 +90,8 @@
66755B821B3B79380013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
66755B841B3B79380013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
66755B851B3B79380013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA641B51EFDB00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA651B51EFDB00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
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; };
@@ -157,6 +160,8 @@
66755B661B3B79380013E67E /* EZAudioDevice.m */,
66755B671B3B79380013E67E /* EZAudioDisplayLink.h */,
66755B681B3B79380013E67E /* EZAudioDisplayLink.m */,
667EEA641B51EFDB00D57FB2 /* EZAudioFFT.h */,
667EEA651B51EFDB00D57FB2 /* EZAudioFFT.m */,
66755B691B3B79380013E67E /* EZAudioFile.h */,
66755B6A1B3B79380013E67E /* EZAudioFile.m */,
66755B6B1B3B79380013E67E /* EZAudioFloatConverter.h */,
@@ -393,6 +398,7 @@
66755B8D1B3B79380013E67E /* EZAudioPlayer.m in Sources */,
9417A9D61872130200D9D37B /* FFTViewController.m in Sources */,
66755B8F1B3B79380013E67E /* EZAudioPlotGL.m in Sources */,
667EEA661B51EFDB00D57FB2 /* EZAudioFFT.m in Sources */,
66755B8A1B3B79380013E67E /* EZAudioFile.m in Sources */,
66755B931B3B79380013E67E /* EZOutput.m in Sources */,
66755B911B3B79380013E67E /* EZAudioUtilities.m in Sources */,
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5053" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5053"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@@ -10,7 +11,7 @@
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="EZAudioFFTExample" id="56">
@@ -647,10 +648,10 @@
</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"/>
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="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"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
@@ -30,30 +30,35 @@
*/
#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>
@interface FFTViewController : NSViewController <EZMicrophoneDelegate, EZAudioFFTDelegate>
#pragma mark - Components
/**
EZAudioPlot for frequency plot
*/
@property (nonatomic,weak) IBOutlet EZAudioPlot *audioPlotFreq;
@property (nonatomic, weak) IBOutlet EZAudioPlot *audioPlotFreq;
/**
EZAudioPlot for time plot
*/
@property (nonatomic,weak) IBOutlet EZAudioPlot *audioPlotTime;
@property (nonatomic, weak) IBOutlet EZAudioPlot *audioPlotTime;
/**
Microphone
A label used to display the maximum frequency (i.e. the frequency with the highest energy) calculated from the FFT.
*/
@property (nonatomic,strong) EZMicrophone *microphone;
@property (nonatomic, weak) IBOutlet NSTextField *maxFrequencyLabel;
/**
The microphone used to get input.
*/
@property (nonatomic, strong) EZMicrophone *microphone;
/**
Used to calculate a rolling FFT of the incoming audio data.
*/
@property (nonatomic, strong) EZAudioFFTRolling *fft;
@end
@@ -25,25 +25,13 @@
#import "FFTViewController.h"
static vDSP_Length const FFTViewControllerFFTWindowSize = 4096;
@interface FFTViewController ()
@property (nonatomic, assign) COMPLEX_SPLIT *A;
@property (nonatomic, assign) FFTSetup FFTSetup;
@property (nonatomic, assign) vDSP_Length log2n;
@property (nonatomic, assign) BOOL isFFTSetup;
@end
@implementation FFTViewController
//------------------------------------------------------------------------------
#pragma mark - Dealloc
//------------------------------------------------------------------------------
- (void)dealloc
{
vDSP_destroy_fftsetup(self.FFTSetup);
free(self.A);
}
//------------------------------------------------------------------------------
#pragma mark - Customize the Audio Plot
//------------------------------------------------------------------------------
@@ -53,117 +41,31 @@
//
// 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;
self.audioPlotTime.plotType = EZPlotTypeBuffer;
//
// 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;
self.audioPlotFreq.shouldFill = YES;
self.audioPlotFreq.plotType = EZPlotTypeBuffer;
self.audioPlotFreq.shouldCenterYAxis = NO;
//
// 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 - FFT
//------------------------------------------------------------------------------
/**
Adapted from http://batmobile.blogs.ilrt.org/fourier-transforms-on-an-iphone/
*/
- (void)createFFTWithBufferSize:(float)bufferSize
withAudioData:(float *)data
{
self.microphone = [EZMicrophone microphoneWithDelegate:self];
//
// Setup the length
// Create an instance of the EZAudioFFTRolling to keep a history of the incoming audio data and calculate the FFT.
//
self.log2n = log2f(bufferSize);
self.fft = [EZAudioFFTRolling fftWithWindowSize:FFTViewControllerFFTWindowSize
sampleRate:self.microphone.audioStreamBasicDescription.mSampleRate
delegate:self];
//
// Calculate the weights array. This is a one-off operation.
// Start the mic
//
_FFTSetup = vDSP_create_fftsetup(self.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
//
self.A = malloc(sizeof(COMPLEX_SPLIT));
self.A->realp = (float *) malloc(nOver2 * sizeof(float));
self.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, self.A, 1, nOver2);
//
// Perform a forward FFT using fftSetup and A
// Results are returned in A
//
vDSP_fft_zrip(_FFTSetup, self.A, 1, self.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 = self.A->realp[i]*self.A->realp[i]+self.A->imagp[i]*self.A->imagp[i];
maxMag = mag > maxMag ? mag : maxMag;
}
for(int i=0; i < nOver2; i++)
{
// Calculate the magnitude
float mag = self.A->realp[i]*self.A->realp[i]+self.A->imagp[i]*self.A->imagp[i];
// Bind the value to be less than 1.0 to fit in the graph
amp[i] = [EZAudioUtilities MAP:mag leftMin:0.0 leftMax:maxMag rightMin:0.0 rightMax:1.0];
}
//
// Update the frequency domain plot
//
[self.audioPlotFreq updateBuffer:amp withBufferSize:nOver2];
[self.microphone startFetchingAudio];
}
//------------------------------------------------------------------------------
@@ -175,28 +77,34 @@
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
{
//
// Calculate the FFT, will trigger EZAudioFFTDelegate
//
[self.fft computeFFTWithBuffer:buffer[0] withBufferSize:bufferSize];
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
//
// Update time domain plot
//
[weakSelf.audioPlotTime updateBuffer:buffer[0]
withBufferSize:bufferSize];
//
// Lazily perform the FFT setup
//
if (!weakSelf.isFFTSetup)
{
[weakSelf createFFTWithBufferSize:bufferSize withAudioData:buffer[0]];
weakSelf.isFFTSetup = YES;
}
});
}
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFTDelegate
//------------------------------------------------------------------------------
- (void) fft:(EZAudioFFT *)fft
updatedWithFFTData:(float *)fftData
bufferSize:(vDSP_Length)bufferSize
{
float maxFrequency = [fft maxFrequency];
NSString *noteName = [EZAudioUtilities noteNameStringForFrequency:maxFrequency
includeOctave:YES];
//
// Perform FFT and update FFT graph
//
[weakSelf updateFFTWithBufferSize:bufferSize
withAudioData:buffer[0]];
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.maxFrequencyLabel.stringValue = [NSString stringWithFormat:@"Highest Note: %@,\nFrequency: %.2f", noteName, maxFrequency];
[weakSelf.audioPlotFreq updateBuffer:fftData withBufferSize:(UInt32)bufferSize];
});
}
@@ -1,47 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment version="1070" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</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="audioPlotFreq" destination="1" id="9lp-OU-kM3"/>
<outlet property="audioPlotTime" destination="aUO-zv-aqE" id="0TL-T2-imj"/>
<outlet property="maxFrequencyLabel" destination="dlx-e6-5CC" id="3QV-3c-qki"/>
<outlet property="view" destination="1" id="2"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="1">
<customView id="1" customClass="EZAudioPlot">
<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"/>
<subviews>
<customView fixedFrame="YES" id="Zcc-CT-67u" customClass="EZAudioPlot">
<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>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="aUO-zv-aqE" customClass="EZAudioPlot">
<rect key="frame" x="18" y="190" width="444" height="64"/>
<constraints>
<constraint firstAttribute="height" constant="64" id="oiN-dY-Vey"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="color">
<color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dlx-e6-5CC">
<rect key="frame" x="16" y="159" width="4" height="22"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="IFE-um-tWr">
<font key="font" size="18" name="HelveticaNeue-Light"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</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"/>
<constraint firstItem="aUO-zv-aqE" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="18" id="9RE-pT-LZj"/>
<constraint firstItem="dlx-e6-5CC" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="18" id="MGj-LS-3mw"/>
<constraint firstAttribute="trailing" secondItem="aUO-zv-aqE" secondAttribute="trailing" constant="18" id="XiD-Ij-Mxf"/>
<constraint firstItem="dlx-e6-5CC" firstAttribute="top" secondItem="aUO-zv-aqE" secondAttribute="bottom" constant="9" id="Z3k-6W-KAH"/>
<constraint firstItem="aUO-zv-aqE" firstAttribute="top" secondItem="1" secondAttribute="top" constant="18" id="jk5-aa-dMV"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
<color key="value" red="0.0078431372550000003" green="0.72156862749999995" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="color">
<color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<point key="canvasLocation" x="156" y="183"/>
</customView>
</objects>
</document>
@@ -24,6 +24,8 @@
66755A791B3B79130013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 66755A641B3B79130013E67E /* TPCircularBuffer.c */; };
66755A7A1B3B79130013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 66755A671B3B79130013E67E /* CHANGELOG */; };
66755A7B1B3B79130013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 66755A681B3B79130013E67E /* VERSION */; };
667EEA571B51EF9F00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA561B51EF9F00D57FB2 /* EZAudioFFT.m */; };
667EEA6A1B51F0D900D57FB2 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 667EEA691B51F0D900D57FB2 /* Accelerate.framework */; };
94056D97185BB0BC00EB94BA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056D96185BB0BC00EB94BA /* Cocoa.framework */; };
94056DA1185BB0BC00EB94BA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94056D9F185BB0BC00EB94BA /* InfoPlist.strings */; };
94056DA3185BB0BC00EB94BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 94056DA2185BB0BC00EB94BA /* main.m */; };
@@ -88,6 +90,9 @@
66755A651B3B79130013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
66755A671B3B79130013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
66755A681B3B79130013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA551B51EF9F00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA561B51EF9F00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
667EEA691B51F0D900D57FB2 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
94056D93185BB0BC00EB94BA /* EZAudioOpenGLWaveformExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioOpenGLWaveformExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
94056D96185BB0BC00EB94BA /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
94056D99185BB0BC00EB94BA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@@ -123,6 +128,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
667EEA6A1B51F0D900D57FB2 /* Accelerate.framework in Frameworks */,
94056DD8185BB0F400EB94BA /* AudioToolbox.framework in Frameworks */,
94056DD9185BB0F400EB94BA /* AudioUnit.framework in Frameworks */,
94056DDA185BB0F400EB94BA /* CoreAudio.framework in Frameworks */,
@@ -154,6 +160,8 @@
66755A491B3B79130013E67E /* EZAudioDevice.m */,
66755A4A1B3B79130013E67E /* EZAudioDisplayLink.h */,
66755A4B1B3B79130013E67E /* EZAudioDisplayLink.m */,
667EEA551B51EF9F00D57FB2 /* EZAudioFFT.h */,
667EEA561B51EF9F00D57FB2 /* EZAudioFFT.m */,
66755A4C1B3B79130013E67E /* EZAudioFile.h */,
66755A4D1B3B79130013E67E /* EZAudioFile.m */,
66755A4E1B3B79130013E67E /* EZAudioFloatConverter.h */,
@@ -215,6 +223,7 @@
94056D95185BB0BC00EB94BA /* Frameworks */ = {
isa = PBXGroup;
children = (
667EEA691B51F0D900D57FB2 /* Accelerate.framework */,
94056DD5185BB0F400EB94BA /* AudioToolbox.framework */,
94056DD6185BB0F400EB94BA /* AudioUnit.framework */,
94056DD7185BB0F400EB94BA /* CoreAudio.framework */,
@@ -389,6 +398,7 @@
66755A701B3B79130013E67E /* EZAudioPlayer.m in Sources */,
94056DAA185BB0BC00EB94BA /* AppDelegate.m in Sources */,
66755A721B3B79130013E67E /* EZAudioPlotGL.m in Sources */,
667EEA571B51EF9F00D57FB2 /* EZAudioFFT.m in Sources */,
66755A6D1B3B79130013E67E /* EZAudioFile.m in Sources */,
66755A761B3B79130013E67E /* EZOutput.m in Sources */,
66755A741B3B79130013E67E /* EZAudioUtilities.m in Sources */,
@@ -1,100 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4439" systemVersion="13A451" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4439"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<action selector="orderFrontStandardAboutPanel:" destination="58" id="142"/>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder">
<connections>
<action selector="alignCenter:" destination="499" id="518"/>
<action selector="alignJustified:" destination="500" id="523"/>
<action selector="alignLeft:" destination="498" id="524"/>
<action selector="alignRight:" destination="501" id="521"/>
<action selector="arrangeInFront:" destination="5" id="39"/>
<action selector="capitalizeWord:" destination="466" id="467"/>
<action selector="centerSelectionInVisibleArea:" destination="210" id="245"/>
<action selector="checkSpelling:" destination="201" id="225"/>
<action selector="clearRecentDocuments:" destination="126" id="127"/>
<action selector="copy:" destination="197" id="224"/>
<action selector="copyFont:" destination="403" id="428"/>
<action selector="copyRuler:" destination="506" id="522"/>
<action selector="cut:" destination="199" id="228"/>
<action selector="delete:" destination="202" id="235"/>
<action selector="hide:" destination="134" id="367"/>
<action selector="hideOtherApplications:" destination="145" id="368"/>
<action selector="loosenKerning:" destination="419" id="435"/>
<action selector="lowerBaseline:" destination="410" id="427"/>
<action selector="lowercaseWord:" destination="465" id="468"/>
<action selector="makeBaseWritingDirectionLeftToRight:" destination="511" id="526"/>
<action selector="makeBaseWritingDirectionNatural:" destination="510" id="525"/>
<action selector="makeBaseWritingDirectionRightToLeft:" destination="512" id="527"/>
<action selector="makeTextWritingDirectionLeftToRight:" destination="516" id="529"/>
<action selector="makeTextWritingDirectionNatural:" destination="515" id="528"/>
<action selector="makeTextWritingDirectionRightToLeft:" destination="517" id="530"/>
<action selector="newDocument:" destination="82" id="373"/>
<action selector="openDocument:" destination="72" id="374"/>
<action selector="orderFrontColorPanel:" destination="401" id="433"/>
<action selector="orderFrontSubstitutionsPanel:" destination="457" id="458"/>
<action selector="paste:" destination="203" id="226"/>
<action selector="pasteAsPlainText:" destination="485" id="486"/>
<action selector="pasteFont:" destination="404" id="436"/>
<action selector="pasteRuler:" destination="507" id="519"/>
<action selector="performClose:" destination="73" id="193"/>
<action selector="performFindPanelAction:" destination="209" id="241"/>
<action selector="performFindPanelAction:" destination="208" id="487"/>
<action selector="performFindPanelAction:" destination="213" id="488"/>
<action selector="performFindPanelAction:" destination="221" id="489"/>
<action selector="performFindPanelAction:" destination="534" id="535"/>
<action selector="performMiniaturize:" destination="23" id="37"/>
<action selector="performZoom:" destination="239" id="240"/>
<action selector="print:" destination="78" id="86"/>
<action selector="raiseBaseline:" destination="409" id="426"/>
<action selector="redo:" destination="215" id="231"/>
<action selector="revertDocumentToSaved:" destination="112" id="364"/>
<action selector="runPageLayout:" destination="77" id="87"/>
<action selector="runToolbarCustomizationPalette:" destination="298" id="365"/>
<action selector="saveDocument:" destination="75" id="362"/>
<action selector="selectAll:" destination="198" id="232"/>
<action selector="showGuessPanel:" destination="204" id="230"/>
<action selector="showHelp:" destination="492" id="493"/>
<action selector="startSpeaking:" destination="196" id="233"/>
<action selector="stopSpeaking:" destination="195" id="227"/>
<action selector="subscript:" destination="408" id="429"/>
<action selector="superscript:" destination="407" id="430"/>
<action selector="tightenKerning:" destination="418" id="431"/>
<action selector="toggleAutomaticDashSubstitution:" destination="460" id="461"/>
<action selector="toggleAutomaticLinkDetection:" destination="354" id="357"/>
<action selector="toggleAutomaticQuoteSubstitution:" destination="351" id="356"/>
<action selector="toggleAutomaticSpellingCorrection:" destination="454" id="456"/>
<action selector="toggleAutomaticTextReplacement:" destination="462" id="463"/>
<action selector="toggleContinuousSpellChecking:" destination="219" id="222"/>
<action selector="toggleGrammarChecking:" destination="346" id="347"/>
<action selector="toggleRuler:" destination="505" id="520"/>
<action selector="toggleSmartInsertDelete:" destination="350" id="355"/>
<action selector="toggleToolbarShown:" destination="297" id="366"/>
<action selector="turnOffKerning:" destination="417" id="441"/>
<action selector="turnOffLigatures:" destination="413" id="440"/>
<action selector="underline:" destination="392" id="432"/>
<action selector="undo:" destination="207" id="223"/>
<action selector="unhideAllApplications:" destination="150" id="370"/>
<action selector="unscript:" destination="406" id="437"/>
<action selector="uppercaseWord:" destination="452" id="464"/>
<action selector="useAllLigatures:" destination="414" id="434"/>
<action selector="useStandardKerning:" destination="416" id="438"/>
<action selector="useStandardLigatures:" destination="412" id="439"/>
</connections>
</customObject>
<customObject id="-3" userLabel="Application">
<connections>
<action selector="terminate:" destination="136" id="449"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="EZAudioOpenGLWaveformExample" id="56">
@@ -102,6 +19,9 @@
<items>
<menuItem title="About EZAudioOpenGLWaveformExample" 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"/>
@@ -116,95 +36,211 @@
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide EZAudioOpenGLWaveformExample" keyEquivalent="h" id="134"/>
<menuItem title="Hide EZAudioOpenGLWaveformExample" 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 title="Show All" id="150"/>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit EZAudioOpenGLWaveformExample" keyEquivalent="q" id="136"/>
<menuItem title="Quit EZAudioOpenGLWaveformExample" 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"/>
<menuItem title="Open…" keyEquivalent="o" id="72"/>
<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"/>
<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"/>
<menuItem title="Save…" keyEquivalent="s" id="75"/>
<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>
<menuItem title="Print…" keyEquivalent="p" id="78"/>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207"/>
<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"/>
<menuItem title="Copy" keyEquivalent="c" id="197"/>
<menuItem title="Paste" keyEquivalent="v" id="203"/>
<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 title="Delete" id="202"/>
<menuItem title="Select All" keyEquivalent="a" id="198"/>
<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"/>
<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 Next" tag="2" keyEquivalent="g" id="208"/>
<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>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210"/>
</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"/>
<menuItem title="Check Document Now" keyEquivalent=";" id="201"/>
<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"/>
<menuItem title="Check Grammar With Spelling" id="346"/>
<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>
@@ -214,18 +250,38 @@
<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"/>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351"/>
<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>
@@ -236,12 +292,21 @@
<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>
@@ -249,8 +314,16 @@
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196"/>
<menuItem title="Stop Speaking" id="195"/>
<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>
@@ -265,13 +338,37 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389"/>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390"/>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391"/>
<menuItem title="Underline" keyEquivalent="u" id="392"/>
<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"/>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395"/>
<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"/>
@@ -279,15 +376,27 @@
<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>
@@ -298,12 +407,21 @@
<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>
@@ -314,30 +432,55 @@
<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"/>
<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>
@@ -346,12 +489,27 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498"/>
<menuItem title="Center" keyEquivalent="|" id="499"/>
<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 title="Align Right" keyEquivalent="}" id="501"/>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
@@ -363,14 +521,23 @@
<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">
@@ -379,14 +546,23 @@
<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>
@@ -394,12 +570,21 @@
<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>
@@ -412,20 +597,39 @@
<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>
<menuItem title="Customize Toolbar…" id="298"/>
</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"/>
<menuItem title="Zoom" id="239"/>
<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"/>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
@@ -433,17 +637,22 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="EZAudioOpenGLWaveformExample Help" keyEquivalent="?" id="492"/>
<menuItem title="EZAudioOpenGLWaveformExample Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="EZAudioOpenGLWaveformExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="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="2560" height="1418"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
@@ -454,14 +663,6 @@
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager">
<connections>
<action selector="addFontTrait:" destination="390" id="421"/>
<action selector="addFontTrait:" destination="391" id="422"/>
<action selector="modifyFont:" destination="395" id="423"/>
<action selector="modifyFont:" destination="394" id="425"/>
<action selector="orderFrontFontPanel:" destination="389" id="424"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -61,6 +61,11 @@
*/
@property (nonatomic, weak) IBOutlet NSPopUpButton *microphoneInputChannelPopUpButton;
/**
The checkbox button used to turn the microphone off/on
*/
@property (nonatomic, weak) IBOutlet NSButton *microphoneSwitch;
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
@@ -226,8 +226,7 @@ withNumberOfChannels:(UInt32)numberOfChannels
//------------------------------------------------------------------------------
- (void)microphone:(EZMicrophone *)microphone
changedDevice:(EZAudioDevice *)device
- (void)microphone:(EZMicrophone *)microphone changedDevice:(EZAudioDevice *)device
{
dispatch_async(dispatch_get_main_queue(), ^{
//
@@ -246,4 +245,25 @@ withNumberOfChannels:(UInt32)numberOfChannels
//------------------------------------------------------------------------------
- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying
{
NSString *title = isPlaying ? @"Microphone On" : @"Microphone Off";
[self setTitle:title forButton:self.microphoneSwitch];
}
//------------------------------------------------------------------------------
#pragma mark - Utility
//------------------------------------------------------------------------------
- (void)setTitle:(NSString *)title forButton:(NSButton *)button
{
NSDictionary *attributes = @{ NSForegroundColorAttributeName : [NSColor whiteColor] };
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title
attributes:attributes];
button.attributedTitle = attributedTitle;
button.attributedAlternateTitle = attributedTitle;
}
//------------------------------------------------------------------------------
@end
@@ -10,6 +10,7 @@
<outlet property="audioPlot" destination="foT-nv-032" id="Baw-Le-z98"/>
<outlet property="microphoneInputChannelPopUpButton" destination="Usd-lp-n8s" id="FbQ-hj-24k"/>
<outlet property="microphoneInputPopUpButton" destination="wBG-jf-wVy" id="thS-Ur-IMj"/>
<outlet property="microphoneSwitch" destination="TbW-ha-PgJ" id="wEZ-dt-f7t"/>
<outlet property="view" destination="hFn-jA-9Se" id="cfu-I4-qhQ"/>
</connections>
</customObject>
@@ -19,104 +20,107 @@
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button translatesAutoresizingMaskIntoConstraints="NO" id="TbW-ha-PgJ">
<rect key="frame" x="339" y="44" width="123" height="18"/>
<constraints>
<constraint firstAttribute="width" constant="119" id="xPL-Un-c5O"/>
</constraints>
<buttonCell key="cell" type="check" title="Microphone On" bezelStyle="regularSquare" imagePosition="right" state="on" inset="2" id="DaM-FV-gba">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleMicrophone:" target="-2" id="Zb5-tE-lf2"/>
</connections>
</button>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UPI-59-15v">
<rect key="frame" x="335" y="15" width="127" height="24"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="VRd-fb-9nH">
<font key="font" metaFont="system"/>
<segments>
<segment label="Buffer" selected="YES"/>
<segment label="Rolling" tag="1"/>
</segments>
</segmentedCell>
<connections>
<action selector="changePlotType:" target="-2" id="BMJ-vA-3ce"/>
</connections>
</segmentedControl>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wBG-jf-wVy" userLabel="microphoneInputPopUpButton">
<rect key="frame" x="18" y="14" width="180" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="175" id="aMw-9p-rHt"/>
</constraints>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="cAL-rs-h1w" id="H5k-ea-wV5">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="15c-sS-jR2">
<items>
<menuItem title="Item 1" state="on" id="cAL-rs-h1w"/>
<menuItem title="Item 2" id="LTz-i3-N0M"/>
<menuItem title="Item 3" id="twD-3N-rcl"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Usd-lp-n8s" userLabel="microphoneInputChannelPopUpButton">
<rect key="frame" x="204" y="14" width="79" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="74" id="oDB-ke-aGz"/>
</constraints>
<popUpButtonCell key="cell" type="push" title="1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Oit-zz-O9w" id="Eyb-QQ-0bg">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="IPB-NH-My1">
<items>
<menuItem title="1" state="on" id="Oit-zz-O9w"/>
<menuItem title="Item 2" id="v3y-Nn-80j"/>
<menuItem title="Item 3" id="IHk-VR-fPC"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AuX-d2-dD9">
<rect key="frame" x="18" y="43" width="36" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Input" id="Fq3-tX-8aU">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PMV-Zt-Wg6">
<rect key="frame" x="204" y="43" width="55" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Channel" id="PTE-g2-mTV">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="foT-nv-032" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="77" width="480" height="195"/>
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<subviews>
<button translatesAutoresizingMaskIntoConstraints="NO" id="TbW-ha-PgJ">
<rect key="frame" x="339" y="47" width="123" height="18"/>
<constraints>
<constraint firstAttribute="width" constant="119" id="xPL-Un-c5O"/>
</constraints>
<buttonCell key="cell" type="check" title="Microphone On" bezelStyle="regularSquare" imagePosition="right" state="on" inset="2" id="DaM-FV-gba">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleMicrophone:" target="-2" id="Zb5-tE-lf2"/>
</connections>
</button>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UPI-59-15v">
<rect key="frame" x="335" y="18" width="127" height="24"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="VRd-fb-9nH">
<font key="font" metaFont="system"/>
<segments>
<segment label="Buffer" selected="YES"/>
<segment label="Rolling" tag="1"/>
</segments>
</segmentedCell>
<connections>
<action selector="changePlotType:" target="-2" id="BMJ-vA-3ce"/>
</connections>
</segmentedControl>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wBG-jf-wVy" userLabel="microphoneInputPopUpButton">
<rect key="frame" x="18" y="17" width="180" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="175" id="aMw-9p-rHt"/>
</constraints>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="cAL-rs-h1w" id="H5k-ea-wV5">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="15c-sS-jR2">
<items>
<menuItem title="Item 1" state="on" id="cAL-rs-h1w"/>
<menuItem title="Item 2" id="LTz-i3-N0M"/>
<menuItem title="Item 3" id="twD-3N-rcl"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Usd-lp-n8s" userLabel="microphoneInputChannelPopUpButton">
<rect key="frame" x="204" y="17" width="79" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="74" id="oDB-ke-aGz"/>
</constraints>
<popUpButtonCell key="cell" type="push" title="1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Oit-zz-O9w" id="Eyb-QQ-0bg">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="IPB-NH-My1">
<items>
<menuItem title="1" state="on" id="Oit-zz-O9w"/>
<menuItem title="Item 2" id="v3y-Nn-80j"/>
<menuItem title="Item 3" id="IHk-VR-fPC"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AuX-d2-dD9">
<rect key="frame" x="18" y="46" width="36" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Input" id="Fq3-tX-8aU">
<font key="font" metaFont="system"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="PMV-Zt-Wg6">
<rect key="frame" x="204" y="46" width="55" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Channel" id="PTE-g2-mTV">
<font key="font" metaFont="system"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="AuX-d2-dD9" firstAttribute="leading" secondItem="foT-nv-032" secondAttribute="leading" constant="20" id="251-JP-6Sa"/>
<constraint firstItem="PMV-Zt-Wg6" firstAttribute="leading" secondItem="AuX-d2-dD9" secondAttribute="trailing" constant="154" id="2EP-1U-pH4"/>
<constraint firstAttribute="bottom" secondItem="wBG-jf-wVy" secondAttribute="bottom" constant="20" id="3kE-rV-Xyk"/>
<constraint firstItem="wBG-jf-wVy" firstAttribute="leading" secondItem="foT-nv-032" secondAttribute="leading" constant="20" id="5BJ-zk-KIK"/>
<constraint firstItem="wBG-jf-wVy" firstAttribute="top" secondItem="AuX-d2-dD9" secondAttribute="bottom" constant="5" id="GPm-pn-f3f"/>
<constraint firstAttribute="bottom" secondItem="UPI-59-15v" secondAttribute="bottom" constant="20" id="NIO-kU-qxG"/>
<constraint firstItem="UPI-59-15v" firstAttribute="top" secondItem="TbW-ha-PgJ" secondAttribute="bottom" constant="8" id="TZN-2g-Vnf"/>
<constraint firstAttribute="trailing" secondItem="TbW-ha-PgJ" secondAttribute="trailing" constant="20" id="mg0-av-TaM"/>
<constraint firstItem="Usd-lp-n8s" firstAttribute="top" secondItem="PMV-Zt-Wg6" secondAttribute="bottom" constant="5" id="nD0-WN-DIk"/>
<constraint firstAttribute="trailing" secondItem="UPI-59-15v" secondAttribute="trailing" constant="20" id="rW1-1W-2K8"/>
<constraint firstItem="Usd-lp-n8s" firstAttribute="leading" secondItem="wBG-jf-wVy" secondAttribute="trailing" constant="11" id="uWS-Ht-6JY"/>
<constraint firstAttribute="bottom" secondItem="Usd-lp-n8s" secondAttribute="bottom" constant="20" id="yZL-HJ-0px"/>
</constraints>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="wBG-jf-wVy" secondAttribute="bottom" constant="17" id="39Q-dq-Ifx"/>
<constraint firstAttribute="trailing" secondItem="foT-nv-032" secondAttribute="trailing" id="4QC-HO-oMa"/>
<constraint firstItem="foT-nv-032" firstAttribute="top" secondItem="hFn-jA-9Se" secondAttribute="top" id="5zo-Yc-OKX"/>
<constraint firstItem="UPI-59-15v" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Usd-lp-n8s" secondAttribute="trailing" constant="11" id="AXw-KY-VEi"/>
<constraint firstItem="Usd-lp-n8s" firstAttribute="top" secondItem="PMV-Zt-Wg6" secondAttribute="bottom" constant="5" id="GZn-x5-gDa"/>
<constraint firstAttribute="trailing" secondItem="UPI-59-15v" secondAttribute="trailing" constant="20" id="Ihi-YB-8cN"/>
<constraint firstItem="AuX-d2-dD9" firstAttribute="leading" secondItem="hFn-jA-9Se" secondAttribute="leading" constant="20" id="RFU-gK-hRd"/>
<constraint firstItem="TbW-ha-PgJ" firstAttribute="top" secondItem="foT-nv-032" secondAttribute="bottom" constant="17" id="aWO-qE-S52"/>
<constraint firstAttribute="bottom" secondItem="UPI-59-15v" secondAttribute="bottom" constant="17" id="biy-0r-WsW"/>
<constraint firstItem="wBG-jf-wVy" firstAttribute="top" secondItem="AuX-d2-dD9" secondAttribute="bottom" constant="5" id="fEE-bx-NVl"/>
<constraint firstItem="UPI-59-15v" firstAttribute="top" secondItem="TbW-ha-PgJ" secondAttribute="bottom" constant="8" id="gMX-Q1-9Ly"/>
<constraint firstAttribute="trailing" secondItem="TbW-ha-PgJ" secondAttribute="trailing" constant="20" id="gek-Wl-IPz"/>
<constraint firstItem="Usd-lp-n8s" firstAttribute="leading" secondItem="wBG-jf-wVy" secondAttribute="trailing" constant="11" id="gqi-4E-1Wf"/>
<constraint firstItem="Usd-lp-n8s" firstAttribute="leading" secondItem="PMV-Zt-Wg6" secondAttribute="leading" id="lT3-RX-en8"/>
<constraint firstAttribute="bottom" secondItem="foT-nv-032" secondAttribute="bottom" id="VKs-UL-eU4"/>
<constraint firstItem="foT-nv-032" firstAttribute="leading" secondItem="hFn-jA-9Se" secondAttribute="leading" id="o4A-j4-xiR"/>
<constraint firstItem="wBG-jf-wVy" firstAttribute="leading" secondItem="hFn-jA-9Se" secondAttribute="leading" constant="20" id="uyC-v9-bP1"/>
<constraint firstAttribute="bottom" secondItem="Usd-lp-n8s" secondAttribute="bottom" constant="17" id="yk6-Fm-gXu"/>
</constraints>
</customView>
</objects>
@@ -24,6 +24,8 @@
66755B5D1B3B79310013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 66755B481B3B79310013E67E /* TPCircularBuffer.c */; };
66755B5E1B3B79310013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 66755B4B1B3B79310013E67E /* CHANGELOG */; };
66755B5F1B3B79310013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 66755B4C1B3B79310013E67E /* VERSION */; };
667EEA631B51EFCF00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA621B51EFCF00D57FB2 /* EZAudioFFT.m */; };
667EEA721B51F0F200D57FB2 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 667EEA711B51F0F200D57FB2 /* Accelerate.framework */; };
941D71B81864C457007D52D8 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 941D71B71864C457007D52D8 /* Cocoa.framework */; };
941D71C21864C457007D52D8 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 941D71C01864C457007D52D8 /* InfoPlist.strings */; };
941D71C41864C457007D52D8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 941D71C31864C457007D52D8 /* main.m */; };
@@ -88,6 +90,9 @@
66755B491B3B79310013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
66755B4B1B3B79310013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
66755B4C1B3B79310013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA611B51EFCF00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA621B51EFCF00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
667EEA711B51F0F200D57FB2 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
941D71B41864C457007D52D8 /* EZAudioPassThroughExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioPassThroughExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
941D71B71864C457007D52D8 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
941D71BA1864C457007D52D8 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@@ -123,6 +128,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
667EEA721B51F0F200D57FB2 /* Accelerate.framework in Frameworks */,
941D721D1864C4C0007D52D8 /* QuartzCore.framework in Frameworks */,
941D721A1864C4AD007D52D8 /* GLKit.framework in Frameworks */,
941D721B1864C4AD007D52D8 /* OpenGL.framework in Frameworks */,
@@ -154,6 +160,8 @@
66755B2D1B3B79310013E67E /* EZAudioDevice.m */,
66755B2E1B3B79310013E67E /* EZAudioDisplayLink.h */,
66755B2F1B3B79310013E67E /* EZAudioDisplayLink.m */,
667EEA611B51EFCF00D57FB2 /* EZAudioFFT.h */,
667EEA621B51EFCF00D57FB2 /* EZAudioFFT.m */,
66755B301B3B79310013E67E /* EZAudioFile.h */,
66755B311B3B79310013E67E /* EZAudioFile.m */,
66755B321B3B79310013E67E /* EZAudioFloatConverter.h */,
@@ -215,6 +223,7 @@
941D71B61864C457007D52D8 /* Frameworks */ = {
isa = PBXGroup;
children = (
667EEA711B51F0F200D57FB2 /* Accelerate.framework */,
941D721C1864C4C0007D52D8 /* QuartzCore.framework */,
941D72181864C4AD007D52D8 /* GLKit.framework */,
941D72191864C4AD007D52D8 /* OpenGL.framework */,
@@ -389,6 +398,7 @@
66755B541B3B79310013E67E /* EZAudioPlayer.m in Sources */,
941D72211864C4D7007D52D8 /* PassThroughViewController.m in Sources */,
66755B561B3B79310013E67E /* EZAudioPlotGL.m in Sources */,
667EEA631B51EFCF00D57FB2 /* EZAudioFFT.m in Sources */,
66755B511B3B79310013E67E /* EZAudioFile.m in Sources */,
66755B5A1B3B79310013E67E /* EZOutput.m in Sources */,
66755B581B3B79310013E67E /* EZAudioUtilities.m in Sources */,
@@ -1,100 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4439" systemVersion="13A451" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4439"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<action selector="orderFrontStandardAboutPanel:" destination="58" id="142"/>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder">
<connections>
<action selector="alignCenter:" destination="499" id="518"/>
<action selector="alignJustified:" destination="500" id="523"/>
<action selector="alignLeft:" destination="498" id="524"/>
<action selector="alignRight:" destination="501" id="521"/>
<action selector="arrangeInFront:" destination="5" id="39"/>
<action selector="capitalizeWord:" destination="466" id="467"/>
<action selector="centerSelectionInVisibleArea:" destination="210" id="245"/>
<action selector="checkSpelling:" destination="201" id="225"/>
<action selector="clearRecentDocuments:" destination="126" id="127"/>
<action selector="copy:" destination="197" id="224"/>
<action selector="copyFont:" destination="403" id="428"/>
<action selector="copyRuler:" destination="506" id="522"/>
<action selector="cut:" destination="199" id="228"/>
<action selector="delete:" destination="202" id="235"/>
<action selector="hide:" destination="134" id="367"/>
<action selector="hideOtherApplications:" destination="145" id="368"/>
<action selector="loosenKerning:" destination="419" id="435"/>
<action selector="lowerBaseline:" destination="410" id="427"/>
<action selector="lowercaseWord:" destination="465" id="468"/>
<action selector="makeBaseWritingDirectionLeftToRight:" destination="511" id="526"/>
<action selector="makeBaseWritingDirectionNatural:" destination="510" id="525"/>
<action selector="makeBaseWritingDirectionRightToLeft:" destination="512" id="527"/>
<action selector="makeTextWritingDirectionLeftToRight:" destination="516" id="529"/>
<action selector="makeTextWritingDirectionNatural:" destination="515" id="528"/>
<action selector="makeTextWritingDirectionRightToLeft:" destination="517" id="530"/>
<action selector="newDocument:" destination="82" id="373"/>
<action selector="openDocument:" destination="72" id="374"/>
<action selector="orderFrontColorPanel:" destination="401" id="433"/>
<action selector="orderFrontSubstitutionsPanel:" destination="457" id="458"/>
<action selector="paste:" destination="203" id="226"/>
<action selector="pasteAsPlainText:" destination="485" id="486"/>
<action selector="pasteFont:" destination="404" id="436"/>
<action selector="pasteRuler:" destination="507" id="519"/>
<action selector="performClose:" destination="73" id="193"/>
<action selector="performFindPanelAction:" destination="209" id="241"/>
<action selector="performFindPanelAction:" destination="208" id="487"/>
<action selector="performFindPanelAction:" destination="213" id="488"/>
<action selector="performFindPanelAction:" destination="221" id="489"/>
<action selector="performFindPanelAction:" destination="534" id="535"/>
<action selector="performMiniaturize:" destination="23" id="37"/>
<action selector="performZoom:" destination="239" id="240"/>
<action selector="print:" destination="78" id="86"/>
<action selector="raiseBaseline:" destination="409" id="426"/>
<action selector="redo:" destination="215" id="231"/>
<action selector="revertDocumentToSaved:" destination="112" id="364"/>
<action selector="runPageLayout:" destination="77" id="87"/>
<action selector="runToolbarCustomizationPalette:" destination="298" id="365"/>
<action selector="saveDocument:" destination="75" id="362"/>
<action selector="selectAll:" destination="198" id="232"/>
<action selector="showGuessPanel:" destination="204" id="230"/>
<action selector="showHelp:" destination="492" id="493"/>
<action selector="startSpeaking:" destination="196" id="233"/>
<action selector="stopSpeaking:" destination="195" id="227"/>
<action selector="subscript:" destination="408" id="429"/>
<action selector="superscript:" destination="407" id="430"/>
<action selector="tightenKerning:" destination="418" id="431"/>
<action selector="toggleAutomaticDashSubstitution:" destination="460" id="461"/>
<action selector="toggleAutomaticLinkDetection:" destination="354" id="357"/>
<action selector="toggleAutomaticQuoteSubstitution:" destination="351" id="356"/>
<action selector="toggleAutomaticSpellingCorrection:" destination="454" id="456"/>
<action selector="toggleAutomaticTextReplacement:" destination="462" id="463"/>
<action selector="toggleContinuousSpellChecking:" destination="219" id="222"/>
<action selector="toggleGrammarChecking:" destination="346" id="347"/>
<action selector="toggleRuler:" destination="505" id="520"/>
<action selector="toggleSmartInsertDelete:" destination="350" id="355"/>
<action selector="toggleToolbarShown:" destination="297" id="366"/>
<action selector="turnOffKerning:" destination="417" id="441"/>
<action selector="turnOffLigatures:" destination="413" id="440"/>
<action selector="underline:" destination="392" id="432"/>
<action selector="undo:" destination="207" id="223"/>
<action selector="unhideAllApplications:" destination="150" id="370"/>
<action selector="unscript:" destination="406" id="437"/>
<action selector="uppercaseWord:" destination="452" id="464"/>
<action selector="useAllLigatures:" destination="414" id="434"/>
<action selector="useStandardKerning:" destination="416" id="438"/>
<action selector="useStandardLigatures:" destination="412" id="439"/>
</connections>
</customObject>
<customObject id="-3" userLabel="Application">
<connections>
<action selector="terminate:" destination="136" id="449"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="EZAudioPassThroughExample" id="56">
@@ -102,6 +19,9 @@
<items>
<menuItem title="About EZAudioPassThroughExample" 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"/>
@@ -116,95 +36,211 @@
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide EZAudioPassThroughExample" keyEquivalent="h" id="134"/>
<menuItem title="Hide EZAudioPassThroughExample" 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 title="Show All" id="150"/>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit EZAudioPassThroughExample" keyEquivalent="q" id="136"/>
<menuItem title="Quit EZAudioPassThroughExample" 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"/>
<menuItem title="Open…" keyEquivalent="o" id="72"/>
<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"/>
<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"/>
<menuItem title="Save…" keyEquivalent="s" id="75"/>
<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>
<menuItem title="Print…" keyEquivalent="p" id="78"/>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207"/>
<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"/>
<menuItem title="Copy" keyEquivalent="c" id="197"/>
<menuItem title="Paste" keyEquivalent="v" id="203"/>
<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 title="Delete" id="202"/>
<menuItem title="Select All" keyEquivalent="a" id="198"/>
<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"/>
<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 Next" tag="2" keyEquivalent="g" id="208"/>
<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>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210"/>
</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"/>
<menuItem title="Check Document Now" keyEquivalent=";" id="201"/>
<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"/>
<menuItem title="Check Grammar With Spelling" id="346"/>
<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>
@@ -214,18 +250,38 @@
<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"/>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351"/>
<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>
@@ -236,12 +292,21 @@
<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>
@@ -249,8 +314,16 @@
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196"/>
<menuItem title="Stop Speaking" id="195"/>
<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>
@@ -265,13 +338,37 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389"/>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390"/>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391"/>
<menuItem title="Underline" keyEquivalent="u" id="392"/>
<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"/>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395"/>
<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"/>
@@ -279,15 +376,27 @@
<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>
@@ -298,12 +407,21 @@
<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>
@@ -314,30 +432,55 @@
<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"/>
<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>
@@ -346,12 +489,27 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498"/>
<menuItem title="Center" keyEquivalent="|" id="499"/>
<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 title="Align Right" keyEquivalent="}" id="501"/>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
@@ -363,14 +521,23 @@
<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">
@@ -379,14 +546,23 @@
<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>
@@ -394,12 +570,21 @@
<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>
@@ -412,20 +597,39 @@
<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>
<menuItem title="Customize Toolbar…" id="298"/>
</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"/>
<menuItem title="Zoom" id="239"/>
<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"/>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
@@ -433,17 +637,21 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="EZAudioPassThroughExample Help" keyEquivalent="?" id="492"/>
<menuItem title="EZAudioPassThroughExample Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="EZAudioPassThroughExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="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="2560" height="1418"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
@@ -454,14 +662,6 @@
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager">
<connections>
<action selector="addFontTrait:" destination="390" id="421"/>
<action selector="addFontTrait:" destination="391" id="422"/>
<action selector="modifyFont:" destination="395" id="423"/>
<action selector="modifyFont:" destination="394" id="425"/>
<action selector="orderFrontFontPanel:" destination="389" id="424"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -39,7 +39,14 @@
/**
The OpenGL based audio plot
*/
@property (nonatomic,weak) IBOutlet EZAudioPlotGL *audioPlot;
@property (nonatomic, weak) IBOutlet EZAudioPlotGL *audioPlot;
//------------------------------------------------------------------------------
/**
The label used to display the microphone state
*/
@property (nonatomic, weak) IBOutlet NSButton *microphoneSwitch;
//------------------------------------------------------------------------------
#pragma mark - Actions
@@ -132,6 +132,14 @@
#pragma mark - EZMicrophoneDelegate
//------------------------------------------------------------------------------
- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying
{
NSString *title = isPlaying ? @"Microphone On" : @"Microphone Off";
[self setTitle:title forButton:self.microphoneSwitch];
}
//------------------------------------------------------------------------------
-(void) microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
@@ -144,6 +152,19 @@
});
}
//------------------------------------------------------------------------------
#pragma mark - Utility
//------------------------------------------------------------------------------
- (void)setTitle:(NSString *)title forButton:(NSButton *)button
{
NSDictionary *attributes = @{ NSForegroundColorAttributeName : [NSColor whiteColor] };
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title
attributes:attributes];
button.attributedTitle = attributedTitle;
button.attributedAlternateTitle = attributedTitle;
}
//------------------------------------------------------------------------------
@end
@@ -1,69 +1,89 @@
<?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="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment version="1070" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PassThroughViewController">
<connections>
<outlet property="audioPlot" destination="szV-uu-KbA" id="KwB-bl-yeS"/>
<outlet property="microphoneSwitch" destination="hej-uQ-uG1" id="fhN-xl-LNP"/>
<outlet property="view" destination="1d9-8y-ung" id="BT4-Db-KNk"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="1d9-8y-ung">
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="szV-uu-KbA" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="42" width="480" height="230"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<subviews>
<box autoresizesSubviews="NO" title="Box" boxType="custom" borderType="none" translatesAutoresizingMaskIntoConstraints="NO" id="eSf-nW-gda">
<rect key="frame" x="0.0" y="0.0" width="480" height="57"/>
<view key="contentView">
<rect key="frame" x="0.0" y="0.0" width="480" height="57"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button translatesAutoresizingMaskIntoConstraints="NO" id="hej-uQ-uG1">
<rect key="frame" x="16" y="16" width="119" height="18"/>
<constraints>
<constraint firstAttribute="height" constant="14" id="fd8-mW-5iG"/>
<constraint firstAttribute="width" constant="115" id="znu-AU-bWg"/>
</constraints>
<buttonCell key="cell" type="check" title="Microphone On" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="k97-dB-fHu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleMicrophone:" target="-2" id="ofz-vX-IjK"/>
</connections>
</button>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="sPx-Eg-cI6">
<rect key="frame" x="335" y="16" width="129" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="125" id="JlH-Js-Z1d"/>
<constraint firstAttribute="height" constant="21" id="hEY-sc-Ib0"/>
</constraints>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="q61-MR-tCv">
<font key="font" metaFont="system"/>
<segments>
<segment label="Buffer" selected="YES"/>
<segment label="Rolling" tag="1"/>
</segments>
</segmentedCell>
<connections>
<action selector="changePlotType:" target="-2" id="UVX-Mg-yXi"/>
</connections>
</segmentedControl>
</subviews>
</view>
<constraints>
<constraint firstAttribute="trailing" secondItem="sPx-Eg-cI6" secondAttribute="trailing" constant="18" id="3dz-EL-GYk"/>
<constraint firstItem="hej-uQ-uG1" firstAttribute="leading" secondItem="eSf-nW-gda" secondAttribute="leading" constant="18" id="QRY-A3-l3d"/>
<constraint firstItem="sPx-Eg-cI6" firstAttribute="centerY" secondItem="eSf-nW-gda" secondAttribute="centerY" id="ZiD-Mc-F6Z"/>
<constraint firstItem="sPx-Eg-cI6" firstAttribute="bottom" secondItem="hej-uQ-uG1" secondAttribute="bottom" id="kMA-Gc-Asn"/>
<constraint firstAttribute="height" constant="57" id="q54-Ma-rT2"/>
</constraints>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" red="0.0" green="0.0" blue="0.0" alpha="0.70000000000000007" colorSpace="calibratedRGB"/>
</box>
</subviews>
<constraints>
<constraint firstItem="eSf-nW-gda" firstAttribute="leading" secondItem="szV-uu-KbA" secondAttribute="leading" id="n5W-wG-XMz"/>
<constraint firstAttribute="bottom" secondItem="eSf-nW-gda" secondAttribute="bottom" id="ob1-us-1L5"/>
<constraint firstAttribute="trailing" secondItem="eSf-nW-gda" secondAttribute="trailing" id="pGc-Rn-8IL"/>
</constraints>
</customView>
<button translatesAutoresizingMaskIntoConstraints="NO" id="hej-uQ-uG1">
<rect key="frame" x="18" y="14" width="119" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="14" id="fd8-mW-5iG"/>
</constraints>
<buttonCell key="cell" type="check" title="Microphone On" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="k97-dB-fHu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleMicrophone:" target="-2" id="ofz-vX-IjK"/>
</connections>
</button>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="sPx-Eg-cI6">
<rect key="frame" x="333" y="11" width="129" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="hEY-sc-Ib0"/>
</constraints>
<segmentedCell key="cell" alignment="left" style="rounded" trackingMode="selectOne" id="q61-MR-tCv">
<font key="font" metaFont="system"/>
<segments>
<segment label="Buffer" selected="YES"/>
<segment label="Rolling" tag="1"/>
</segments>
</segmentedCell>
<connections>
<action selector="changePlotType:" target="-2" id="UVX-Mg-yXi"/>
</connections>
</segmentedControl>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="szV-uu-KbA" secondAttribute="bottom" id="8NU-Oj-lK1"/>
<constraint firstAttribute="trailing" secondItem="szV-uu-KbA" secondAttribute="trailing" id="AVW-CO-N2Q"/>
<constraint firstItem="szV-uu-KbA" firstAttribute="top" secondItem="1d9-8y-ung" secondAttribute="top" id="DM4-bU-zuP"/>
<constraint firstItem="sPx-Eg-cI6" firstAttribute="top" secondItem="szV-uu-KbA" secondAttribute="bottom" constant="8" id="EFb-mI-KZS"/>
<constraint firstAttribute="trailing" secondItem="sPx-Eg-cI6" secondAttribute="trailing" constant="20" id="MiO-PO-tmm"/>
<constraint firstItem="hej-uQ-uG1" firstAttribute="leading" secondItem="1d9-8y-ung" secondAttribute="leading" constant="20" id="NJE-fd-586"/>
<constraint firstItem="szV-uu-KbA" firstAttribute="leading" secondItem="1d9-8y-ung" secondAttribute="leading" id="Qkq-oi-gx2"/>
<constraint firstAttribute="bottom" secondItem="hej-uQ-uG1" secondAttribute="bottom" constant="16" id="UXq-4r-K0N"/>
<constraint firstAttribute="bottom" secondItem="sPx-Eg-cI6" secondAttribute="bottom" constant="13" id="V0F-aH-MAE"/>
<constraint firstItem="hej-uQ-uG1" firstAttribute="top" secondItem="szV-uu-KbA" secondAttribute="bottom" constant="12" id="cPy-qk-vL2"/>
</constraints>
</customView>
</objects>
</document>
</document>
@@ -25,6 +25,8 @@
66755AB21B3B791C0013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 66755A9D1B3B791C0013E67E /* TPCircularBuffer.c */; };
66755AB31B3B791C0013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 66755AA01B3B791C0013E67E /* CHANGELOG */; };
66755AB41B3B791C0013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 66755AA11B3B791C0013E67E /* VERSION */; };
667EEA5A1B51EFAA00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA591B51EFAA00D57FB2 /* EZAudioFFT.m */; };
667EEA6C1B51F0E000D57FB2 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 667EEA6B1B51F0E000D57FB2 /* Accelerate.framework */; };
94056EFB185BD83400EB94BA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056EFA185BD83400EB94BA /* Cocoa.framework */; };
94056F05185BD83400EB94BA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94056F03185BD83400EB94BA /* InfoPlist.strings */; };
94056F07185BD83400EB94BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 94056F06185BD83400EB94BA /* main.m */; };
@@ -90,6 +92,9 @@
66755A9E1B3B791C0013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
66755AA01B3B791C0013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
66755AA11B3B791C0013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA581B51EFAA00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA591B51EFAA00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
667EEA6B1B51F0E000D57FB2 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
94056EF7185BD83400EB94BA /* EZAudioPlayFileExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioPlayFileExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
94056EFA185BD83400EB94BA /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
94056EFD185BD83400EB94BA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@@ -125,6 +130,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
667EEA6C1B51F0E000D57FB2 /* Accelerate.framework in Frameworks */,
94056F65185BDB4700EB94BA /* AudioToolbox.framework in Frameworks */,
94056F66185BDB4700EB94BA /* AudioUnit.framework in Frameworks */,
94056F67185BDB4700EB94BA /* CoreAudio.framework in Frameworks */,
@@ -156,6 +162,8 @@
66755A821B3B791C0013E67E /* EZAudioDevice.m */,
66755A831B3B791C0013E67E /* EZAudioDisplayLink.h */,
66755A841B3B791C0013E67E /* EZAudioDisplayLink.m */,
667EEA581B51EFAA00D57FB2 /* EZAudioFFT.h */,
667EEA591B51EFAA00D57FB2 /* EZAudioFFT.m */,
66755A851B3B791C0013E67E /* EZAudioFile.h */,
66755A861B3B791C0013E67E /* EZAudioFile.m */,
66755A871B3B791C0013E67E /* EZAudioFloatConverter.h */,
@@ -217,6 +225,7 @@
94056EF9185BD83400EB94BA /* Frameworks */ = {
isa = PBXGroup;
children = (
667EEA6B1B51F0E000D57FB2 /* Accelerate.framework */,
94056F62185BDB4700EB94BA /* AudioToolbox.framework */,
94056F63185BDB4700EB94BA /* AudioUnit.framework */,
94056F64185BDB4700EB94BA /* CoreAudio.framework */,
@@ -393,6 +402,7 @@
66755AA91B3B791C0013E67E /* EZAudioPlayer.m in Sources */,
94056F31185BD86D00EB94BA /* PlayFileViewController.m in Sources */,
66755AAB1B3B791C0013E67E /* EZAudioPlotGL.m in Sources */,
667EEA5A1B51EFAA00D57FB2 /* EZAudioFFT.m in Sources */,
66755AA61B3B791C0013E67E /* EZAudioFile.m in Sources */,
66755AAF1B3B791C0013E67E /* EZOutput.m in Sources */,
66755AAD1B3B791C0013E67E /* EZAudioUtilities.m in Sources */,
@@ -1,100 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4439" systemVersion="13A451" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4439"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<action selector="orderFrontStandardAboutPanel:" destination="58" id="142"/>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder">
<connections>
<action selector="alignCenter:" destination="499" id="518"/>
<action selector="alignJustified:" destination="500" id="523"/>
<action selector="alignLeft:" destination="498" id="524"/>
<action selector="alignRight:" destination="501" id="521"/>
<action selector="arrangeInFront:" destination="5" id="39"/>
<action selector="capitalizeWord:" destination="466" id="467"/>
<action selector="centerSelectionInVisibleArea:" destination="210" id="245"/>
<action selector="checkSpelling:" destination="201" id="225"/>
<action selector="clearRecentDocuments:" destination="126" id="127"/>
<action selector="copy:" destination="197" id="224"/>
<action selector="copyFont:" destination="403" id="428"/>
<action selector="copyRuler:" destination="506" id="522"/>
<action selector="cut:" destination="199" id="228"/>
<action selector="delete:" destination="202" id="235"/>
<action selector="hide:" destination="134" id="367"/>
<action selector="hideOtherApplications:" destination="145" id="368"/>
<action selector="loosenKerning:" destination="419" id="435"/>
<action selector="lowerBaseline:" destination="410" id="427"/>
<action selector="lowercaseWord:" destination="465" id="468"/>
<action selector="makeBaseWritingDirectionLeftToRight:" destination="511" id="526"/>
<action selector="makeBaseWritingDirectionNatural:" destination="510" id="525"/>
<action selector="makeBaseWritingDirectionRightToLeft:" destination="512" id="527"/>
<action selector="makeTextWritingDirectionLeftToRight:" destination="516" id="529"/>
<action selector="makeTextWritingDirectionNatural:" destination="515" id="528"/>
<action selector="makeTextWritingDirectionRightToLeft:" destination="517" id="530"/>
<action selector="newDocument:" destination="82" id="373"/>
<action selector="openDocument:" destination="72" id="374"/>
<action selector="orderFrontColorPanel:" destination="401" id="433"/>
<action selector="orderFrontSubstitutionsPanel:" destination="457" id="458"/>
<action selector="paste:" destination="203" id="226"/>
<action selector="pasteAsPlainText:" destination="485" id="486"/>
<action selector="pasteFont:" destination="404" id="436"/>
<action selector="pasteRuler:" destination="507" id="519"/>
<action selector="performClose:" destination="73" id="193"/>
<action selector="performFindPanelAction:" destination="209" id="241"/>
<action selector="performFindPanelAction:" destination="208" id="487"/>
<action selector="performFindPanelAction:" destination="213" id="488"/>
<action selector="performFindPanelAction:" destination="221" id="489"/>
<action selector="performFindPanelAction:" destination="534" id="535"/>
<action selector="performMiniaturize:" destination="23" id="37"/>
<action selector="performZoom:" destination="239" id="240"/>
<action selector="print:" destination="78" id="86"/>
<action selector="raiseBaseline:" destination="409" id="426"/>
<action selector="redo:" destination="215" id="231"/>
<action selector="revertDocumentToSaved:" destination="112" id="364"/>
<action selector="runPageLayout:" destination="77" id="87"/>
<action selector="runToolbarCustomizationPalette:" destination="298" id="365"/>
<action selector="saveDocument:" destination="75" id="362"/>
<action selector="selectAll:" destination="198" id="232"/>
<action selector="showGuessPanel:" destination="204" id="230"/>
<action selector="showHelp:" destination="492" id="493"/>
<action selector="startSpeaking:" destination="196" id="233"/>
<action selector="stopSpeaking:" destination="195" id="227"/>
<action selector="subscript:" destination="408" id="429"/>
<action selector="superscript:" destination="407" id="430"/>
<action selector="tightenKerning:" destination="418" id="431"/>
<action selector="toggleAutomaticDashSubstitution:" destination="460" id="461"/>
<action selector="toggleAutomaticLinkDetection:" destination="354" id="357"/>
<action selector="toggleAutomaticQuoteSubstitution:" destination="351" id="356"/>
<action selector="toggleAutomaticSpellingCorrection:" destination="454" id="456"/>
<action selector="toggleAutomaticTextReplacement:" destination="462" id="463"/>
<action selector="toggleContinuousSpellChecking:" destination="219" id="222"/>
<action selector="toggleGrammarChecking:" destination="346" id="347"/>
<action selector="toggleRuler:" destination="505" id="520"/>
<action selector="toggleSmartInsertDelete:" destination="350" id="355"/>
<action selector="toggleToolbarShown:" destination="297" id="366"/>
<action selector="turnOffKerning:" destination="417" id="441"/>
<action selector="turnOffLigatures:" destination="413" id="440"/>
<action selector="underline:" destination="392" id="432"/>
<action selector="undo:" destination="207" id="223"/>
<action selector="unhideAllApplications:" destination="150" id="370"/>
<action selector="unscript:" destination="406" id="437"/>
<action selector="uppercaseWord:" destination="452" id="464"/>
<action selector="useAllLigatures:" destination="414" id="434"/>
<action selector="useStandardKerning:" destination="416" id="438"/>
<action selector="useStandardLigatures:" destination="412" id="439"/>
</connections>
</customObject>
<customObject id="-3" userLabel="Application">
<connections>
<action selector="terminate:" destination="136" id="449"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="EZAudioPlayFileExample" id="56">
@@ -102,6 +19,9 @@
<items>
<menuItem title="About EZAudioPlayFileExample" 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"/>
@@ -116,95 +36,211 @@
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide EZAudioPlayFileExample" keyEquivalent="h" id="134"/>
<menuItem title="Hide EZAudioPlayFileExample" 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 title="Show All" id="150"/>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit EZAudioPlayFileExample" keyEquivalent="q" id="136"/>
<menuItem title="Quit EZAudioPlayFileExample" 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"/>
<menuItem title="Open…" keyEquivalent="o" id="72"/>
<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"/>
<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"/>
<menuItem title="Save…" keyEquivalent="s" id="75"/>
<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>
<menuItem title="Print…" keyEquivalent="p" id="78"/>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207"/>
<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"/>
<menuItem title="Copy" keyEquivalent="c" id="197"/>
<menuItem title="Paste" keyEquivalent="v" id="203"/>
<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 title="Delete" id="202"/>
<menuItem title="Select All" keyEquivalent="a" id="198"/>
<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"/>
<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 Next" tag="2" keyEquivalent="g" id="208"/>
<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>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210"/>
</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"/>
<menuItem title="Check Document Now" keyEquivalent=";" id="201"/>
<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"/>
<menuItem title="Check Grammar With Spelling" id="346"/>
<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>
@@ -214,18 +250,38 @@
<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"/>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351"/>
<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>
@@ -236,12 +292,21 @@
<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>
@@ -249,8 +314,16 @@
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196"/>
<menuItem title="Stop Speaking" id="195"/>
<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>
@@ -265,13 +338,37 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389"/>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390"/>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391"/>
<menuItem title="Underline" keyEquivalent="u" id="392"/>
<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"/>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395"/>
<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"/>
@@ -279,15 +376,27 @@
<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>
@@ -298,12 +407,21 @@
<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>
@@ -314,30 +432,55 @@
<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"/>
<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>
@@ -346,12 +489,27 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498"/>
<menuItem title="Center" keyEquivalent="|" id="499"/>
<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 title="Align Right" keyEquivalent="}" id="501"/>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
@@ -363,14 +521,23 @@
<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">
@@ -379,14 +546,23 @@
<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>
@@ -394,12 +570,21 @@
<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>
@@ -412,20 +597,39 @@
<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>
<menuItem title="Customize Toolbar…" id="298"/>
</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"/>
<menuItem title="Zoom" id="239"/>
<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"/>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
@@ -433,17 +637,21 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="EZAudioPlayFileExample Help" keyEquivalent="?" id="492"/>
<menuItem title="EZAudioPlayFileExample Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="EZAudioPlayFileExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="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="2560" height="1418"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
@@ -454,14 +662,6 @@
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager">
<connections>
<action selector="addFontTrait:" destination="390" id="421"/>
<action selector="addFontTrait:" destination="391" id="422"/>
<action selector="modifyFont:" destination="395" id="423"/>
<action selector="modifyFont:" destination="394" id="425"/>
<action selector="orderFrontFontPanel:" destination="389" id="424"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -30,222 +30,249 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Lz1-Gs-1lD" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="0.0" width="480" height="146"/>
<rect key="frame" x="0.0" y="0.0" width="480" height="366"/>
<subviews>
<box autoresizesSubviews="NO" title="Box" boxType="custom" borderType="none" translatesAutoresizingMaskIntoConstraints="NO" id="woe-PM-Kco">
<rect key="frame" x="0.0" y="124" width="480" height="242"/>
<view key="contentView">
<rect key="frame" x="0.0" y="0.0" width="480" height="242"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2Ma-jj-U3z">
<rect key="frame" x="12" y="172" width="125" height="32"/>
<buttonCell key="cell" type="push" title="Choose File..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="KLq-bf-Xkh">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="openFile:" target="-2" id="3QB-hU-LDl"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0eT-7c-7fJ">
<rect key="frame" x="140" y="184" width="36" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" sendsActionOnEndEditing="YES" alignment="left" title="Label" id="vXQ-HF-vLX">
<font key="font" metaFont="cellTitle"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OQp-Lr-dlS">
<rect key="frame" x="12" y="139" width="125" height="32"/>
<buttonCell key="cell" type="push" title="Play" alternateTitle="Pause" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Z2A-7U-sb6">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="play:" target="-2" id="y83-JF-y4e"/>
</connections>
</button>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bZW-tA-C61">
<rect key="frame" x="335" y="144" width="129" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="125" id="MeF-BC-3tU"/>
</constraints>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="8U1-ER-vPJ">
<font key="font" metaFont="system"/>
<segments>
<segment label="Buffer" selected="YES"/>
<segment label="Rolling" tag="1"/>
</segments>
</segmentedCell>
<connections>
<action selector="changePlotType:" target="-2" id="alU-Rf-22L"/>
</connections>
</segmentedControl>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CFP-v0-TzQ">
<rect key="frame" x="117" y="94" width="269" height="20"/>
<sliderCell key="cell" continuous="YES" alignment="left" maxValue="100" doubleValue="9.3380614657210401" tickMarkPosition="above" sliderType="linear" id="gPc-pN-dmP"/>
<connections>
<action selector="seekToFrame:" target="-2" id="iVY-so-6X2"/>
</connections>
</slider>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vj5-qT-JkR">
<rect key="frame" x="117" y="69" width="269" height="20"/>
<sliderCell key="cell" continuous="YES" alignment="left" minValue="128" maxValue="1024" doubleValue="128" tickMarkPosition="above" sliderType="linear" id="uRZ-Kf-cgJ"/>
<connections>
<action selector="changeRollingHistoryLength:" target="-2" id="eYD-H1-n52"/>
</connections>
</slider>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7AB-VA-xL3">
<rect key="frame" x="16" y="121" width="53" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Volume:" id="GAa-Hp-OlV">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Fw5-pm-4w0">
<rect key="frame" x="16" y="96" width="58" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Position:" id="9hW-4Z-OEW">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Aa9-nc-WHJ">
<rect key="frame" x="16" y="71" width="96" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Rolling Length:" id="Mfs-zu-sCx">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3ul-3w-l3S">
<rect key="frame" x="390" y="121" width="72" height="16"/>
<constraints>
<constraint firstAttribute="width" constant="68" id="H4m-6Q-Jin"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="0.00" id="vlK-Hb-Yca">
<numberFormatter key="formatter" formatterBehavior="custom10_4" minimumIntegerDigits="1" maximumIntegerDigits="1" minimumFractionDigits="2" maximumFractionDigits="2" id="bBU-vS-tEB">
<metadata>
<real key="inspectorSampleValue" value="44"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rRH-oS-VV3">
<rect key="frame" x="117" y="119" width="269" height="20"/>
<sliderCell key="cell" continuous="YES" state="on" alignment="left" maxValue="1" doubleValue="0.5" tickMarkPosition="above" sliderType="linear" id="xbX-Ce-da5"/>
<connections>
<action selector="changeVolume:" target="-2" id="iKx-7d-34D"/>
</connections>
</slider>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vKe-ey-hXI">
<rect key="frame" x="390" y="71" width="72" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="0" id="JiA-3H-vb2">
<numberFormatter key="formatter" formatterBehavior="custom10_4" minimumIntegerDigits="0" maximumIntegerDigits="42" id="AYM-Tu-k5w">
<metadata>
<real key="inspectorSampleValue" value="44"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0LV-Bi-dGz" userLabel="microphoneInputPopUpButton">
<rect key="frame" x="16" y="13" width="180" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="175" id="2C5-hq-caw"/>
</constraints>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="a7m-V2-Mw8" id="VLU-oW-zia">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="uLv-18-vra">
<items>
<menuItem title="Item 1" state="on" id="a7m-V2-Mw8"/>
<menuItem title="Item 2" id="qJe-zH-SrZ"/>
<menuItem title="Item 3" id="zlE-dQ-R4x"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="RRH-G6-xkQ">
<rect key="frame" x="16" y="46" width="50" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Output:" id="2OQ-1o-1vp">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KYm-Io-VNv">
<rect key="frame" x="390" y="96" width="72" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="0" id="gfS-wb-pFu">
<numberFormatter key="formatter" formatterBehavior="custom10_4" minimumIntegerDigits="0" maximumIntegerDigits="42" id="py5-BY-fQN">
<metadata>
<real key="inspectorSampleValue" value="44"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="5xb-MK-C8b">
<rect key="frame" x="442" y="14" width="22" height="18"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="right" alignment="right" state="on" inset="2" id="O83-sN-k0z">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="changeShouldLoop:" target="-2" id="lJN-Pe-JWA"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="TPR-Ta-wlb">
<rect key="frame" x="407" y="16" width="35" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Loop" id="Tok-s1-Gjv">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<constraints>
<constraint firstItem="2Ma-jj-U3z" firstAttribute="leading" secondItem="OQp-Lr-dlS" secondAttribute="leading" id="65r-3l-UpC"/>
<constraint firstItem="bZW-tA-C61" firstAttribute="top" secondItem="OQp-Lr-dlS" secondAttribute="top" id="68U-wj-F2c"/>
<constraint firstItem="vKe-ey-hXI" firstAttribute="trailing" secondItem="KYm-Io-VNv" secondAttribute="trailing" id="6r9-KH-IXj"/>
<constraint firstItem="RRH-G6-xkQ" firstAttribute="top" secondItem="Aa9-nc-WHJ" secondAttribute="bottom" constant="9" id="ARD-0e-VM7"/>
<constraint firstItem="rRH-oS-VV3" firstAttribute="baseline" secondItem="7AB-VA-xL3" secondAttribute="baseline" id="ASG-bU-1Vn"/>
<constraint firstItem="KYm-Io-VNv" firstAttribute="leading" secondItem="CFP-v0-TzQ" secondAttribute="trailing" constant="8" symbolic="YES" id="CvB-yq-Kw5"/>
<constraint firstAttribute="trailing" secondItem="bZW-tA-C61" secondAttribute="trailing" constant="18" id="DqD-RM-NfD"/>
<constraint firstItem="0LV-Bi-dGz" firstAttribute="bottom" secondItem="5xb-MK-C8b" secondAttribute="bottom" id="Eo3-Ds-Pga"/>
<constraint firstItem="7AB-VA-xL3" firstAttribute="leading" secondItem="Fw5-pm-4w0" secondAttribute="leading" id="F4w-hP-VrP"/>
<constraint firstItem="vj5-qT-JkR" firstAttribute="baseline" secondItem="Aa9-nc-WHJ" secondAttribute="baseline" id="FyT-aB-ZMd"/>
<constraint firstItem="Fw5-pm-4w0" firstAttribute="top" secondItem="7AB-VA-xL3" secondAttribute="bottom" constant="9" id="HHI-Px-CUW"/>
<constraint firstItem="RRH-G6-xkQ" firstAttribute="leading" secondItem="0LV-Bi-dGz" secondAttribute="leading" id="Hpy-j7-Sn4"/>
<constraint firstItem="0eT-7c-7fJ" firstAttribute="leading" secondItem="2Ma-jj-U3z" secondAttribute="trailing" constant="11" id="I84-HZ-kvK"/>
<constraint firstItem="OQp-Lr-dlS" firstAttribute="trailing" secondItem="2Ma-jj-U3z" secondAttribute="trailing" id="JSU-sV-ydn"/>
<constraint firstAttribute="bottom" secondItem="TPR-Ta-wlb" secondAttribute="bottom" constant="16" id="NHb-lI-raQ"/>
<constraint firstItem="5xb-MK-C8b" firstAttribute="leading" secondItem="TPR-Ta-wlb" secondAttribute="trailing" constant="4" id="OcY-La-p2F"/>
<constraint firstAttribute="bottom" secondItem="0LV-Bi-dGz" secondAttribute="bottom" constant="16" id="Su4-hr-dIF"/>
<constraint firstItem="7AB-VA-xL3" firstAttribute="top" secondItem="OQp-Lr-dlS" secondAttribute="bottom" constant="9" id="U54-Sp-UR9"/>
<constraint firstItem="KYm-Io-VNv" firstAttribute="baseline" secondItem="CFP-v0-TzQ" secondAttribute="baseline" id="WYP-6b-bar"/>
<constraint firstItem="KYm-Io-VNv" firstAttribute="leading" secondItem="vKe-ey-hXI" secondAttribute="leading" id="WkB-Br-hx8"/>
<constraint firstItem="CFP-v0-TzQ" firstAttribute="leading" secondItem="rRH-oS-VV3" secondAttribute="leading" id="YYb-HP-3oI"/>
<constraint firstItem="0LV-Bi-dGz" firstAttribute="top" secondItem="RRH-G6-xkQ" secondAttribute="bottom" constant="9" id="ZW9-Wz-NjB"/>
<constraint firstItem="bZW-tA-C61" firstAttribute="trailing" secondItem="5xb-MK-C8b" secondAttribute="trailing" id="a4v-Da-5OI"/>
<constraint firstItem="vj5-qT-JkR" firstAttribute="leading" secondItem="Aa9-nc-WHJ" secondAttribute="trailing" constant="9" id="bJy-fK-Mgx"/>
<constraint firstItem="rRH-oS-VV3" firstAttribute="baseline" secondItem="3ul-3w-l3S" secondAttribute="baseline" id="bfM-wb-rHx"/>
<constraint firstItem="7AB-VA-xL3" firstAttribute="leading" secondItem="OQp-Lr-dlS" secondAttribute="leading" id="dta-hH-v59"/>
<constraint firstItem="Fw5-pm-4w0" firstAttribute="leading" secondItem="Aa9-nc-WHJ" secondAttribute="leading" id="e3o-sk-vrf"/>
<constraint firstItem="KYm-Io-VNv" firstAttribute="trailing" secondItem="3ul-3w-l3S" secondAttribute="trailing" id="eZB-I6-kCg"/>
<constraint firstAttribute="height" constant="242" id="gIM-zm-GWO"/>
<constraint firstItem="2Ma-jj-U3z" firstAttribute="top" secondItem="0eT-7c-7fJ" secondAttribute="top" id="hRy-MT-4On"/>
<constraint firstItem="OQp-Lr-dlS" firstAttribute="top" secondItem="2Ma-jj-U3z" secondAttribute="bottom" constant="12" symbolic="YES" id="i9A-k5-5Qa"/>
<constraint firstItem="3ul-3w-l3S" firstAttribute="leading" secondItem="KYm-Io-VNv" secondAttribute="leading" id="jNp-BV-Sn1"/>
<constraint firstItem="CFP-v0-TzQ" firstAttribute="leading" secondItem="vj5-qT-JkR" secondAttribute="leading" id="jlK-cp-ukV"/>
<constraint firstAttribute="trailing" secondItem="3ul-3w-l3S" secondAttribute="trailing" constant="20" id="lUf-2h-95p"/>
<constraint firstItem="CFP-v0-TzQ" firstAttribute="baseline" secondItem="Fw5-pm-4w0" secondAttribute="baseline" id="lVm-7v-XFC"/>
<constraint firstItem="Aa9-nc-WHJ" firstAttribute="top" secondItem="Fw5-pm-4w0" secondAttribute="bottom" constant="9" id="mep-8V-ybk"/>
<constraint firstItem="2Ma-jj-U3z" firstAttribute="leading" secondItem="woe-PM-Kco" secondAttribute="leading" constant="18" id="ufW-Fo-f6i"/>
<constraint firstItem="RRH-G6-xkQ" firstAttribute="leading" secondItem="Aa9-nc-WHJ" secondAttribute="leading" id="v6o-ED-CBK"/>
<constraint firstItem="vKe-ey-hXI" firstAttribute="leading" secondItem="vj5-qT-JkR" secondAttribute="trailing" constant="8" symbolic="YES" id="x5P-WA-MWS"/>
<constraint firstItem="3ul-3w-l3S" firstAttribute="leading" secondItem="rRH-oS-VV3" secondAttribute="trailing" constant="8" symbolic="YES" id="yQv-xx-Toh"/>
<constraint firstItem="vj5-qT-JkR" firstAttribute="baseline" secondItem="vKe-ey-hXI" secondAttribute="baseline" id="ysL-Tn-bng"/>
</constraints>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" red="0.0" green="0.0" blue="0.0" alpha="0.70000000000000007" colorSpace="calibratedRGB"/>
</box>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="woe-PM-Kco" secondAttribute="trailing" id="IfY-Ff-46n"/>
<constraint firstItem="woe-PM-Kco" firstAttribute="leading" secondItem="Lz1-Gs-1lD" secondAttribute="leading" id="UzR-Mq-ujC"/>
<constraint firstItem="woe-PM-Kco" firstAttribute="top" secondItem="Lz1-Gs-1lD" secondAttribute="top" id="yqN-Hf-0Wn"/>
</constraints>
</customView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2Ma-jj-U3z">
<rect key="frame" x="12" y="320" width="125" height="32"/>
<buttonCell key="cell" type="push" title="Choose File..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="KLq-bf-Xkh">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="openFile:" target="-2" id="3QB-hU-LDl"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0eT-7c-7fJ">
<rect key="frame" x="140" y="332" width="36" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" sendsActionOnEndEditing="YES" alignment="left" title="Label" id="vXQ-HF-vLX">
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OQp-Lr-dlS">
<rect key="frame" x="12" y="287" width="125" height="32"/>
<buttonCell key="cell" type="push" title="Play" alternateTitle="Pause" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Z2A-7U-sb6">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="play:" target="-2" id="y83-JF-y4e"/>
</connections>
</button>
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bZW-tA-C61">
<rect key="frame" x="335" y="292" width="129" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="125" id="A3V-sd-Jab"/>
</constraints>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="8U1-ER-vPJ">
<font key="font" metaFont="system"/>
<segments>
<segment label="Buffer" selected="YES"/>
<segment label="Rolling" tag="1"/>
</segments>
</segmentedCell>
<connections>
<action selector="changePlotType:" target="-2" id="alU-Rf-22L"/>
</connections>
</segmentedControl>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CFP-v0-TzQ">
<rect key="frame" x="117" y="242" width="269" height="20"/>
<sliderCell key="cell" continuous="YES" alignment="left" maxValue="100" doubleValue="9.3380614657210401" tickMarkPosition="above" sliderType="linear" id="gPc-pN-dmP"/>
<connections>
<action selector="seekToFrame:" target="-2" id="iVY-so-6X2"/>
</connections>
</slider>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vj5-qT-JkR">
<rect key="frame" x="117" y="217" width="269" height="20"/>
<sliderCell key="cell" continuous="YES" alignment="left" minValue="128" maxValue="1024" doubleValue="128" tickMarkPosition="above" sliderType="linear" id="uRZ-Kf-cgJ"/>
<connections>
<action selector="changeRollingHistoryLength:" target="-2" id="eYD-H1-n52"/>
</connections>
</slider>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7AB-VA-xL3">
<rect key="frame" x="16" y="269" width="53" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Volume:" id="GAa-Hp-OlV">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Fw5-pm-4w0">
<rect key="frame" x="16" y="244" width="58" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Position:" id="9hW-4Z-OEW">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Aa9-nc-WHJ">
<rect key="frame" x="16" y="219" width="96" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Rolling Length:" id="Mfs-zu-sCx">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3ul-3w-l3S">
<rect key="frame" x="390" y="269" width="72" height="16"/>
<constraints>
<constraint firstAttribute="width" constant="68" id="eyi-2x-AqF"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="0.00" id="vlK-Hb-Yca">
<numberFormatter key="formatter" formatterBehavior="custom10_4" minimumIntegerDigits="1" maximumIntegerDigits="1" minimumFractionDigits="2" maximumFractionDigits="2" id="bBU-vS-tEB">
<metadata>
<real key="inspectorSampleValue" value="44"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<slider verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rRH-oS-VV3">
<rect key="frame" x="117" y="267" width="269" height="20"/>
<sliderCell key="cell" continuous="YES" state="on" alignment="left" maxValue="1" doubleValue="0.5" tickMarkPosition="above" sliderType="linear" id="xbX-Ce-da5"/>
<connections>
<action selector="changeVolume:" target="-2" id="iKx-7d-34D"/>
</connections>
</slider>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vKe-ey-hXI">
<rect key="frame" x="390" y="219" width="72" height="16"/>
<constraints>
<constraint firstAttribute="width" constant="68" id="7dV-vH-IBh"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="0" id="JiA-3H-vb2">
<numberFormatter key="formatter" formatterBehavior="custom10_4" minimumIntegerDigits="0" maximumIntegerDigits="42" id="AYM-Tu-k5w">
<metadata>
<real key="inspectorSampleValue" value="44"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0LV-Bi-dGz" userLabel="microphoneInputPopUpButton">
<rect key="frame" x="16" y="161" width="180" height="26"/>
<constraints>
<constraint firstAttribute="width" constant="175" id="fDF-j7-LMD"/>
</constraints>
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="a7m-V2-Mw8" id="VLU-oW-zia">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="uLv-18-vra">
<items>
<menuItem title="Item 1" state="on" id="a7m-V2-Mw8"/>
<menuItem title="Item 2" id="qJe-zH-SrZ"/>
<menuItem title="Item 3" id="zlE-dQ-R4x"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="RRH-G6-xkQ">
<rect key="frame" x="16" y="194" width="50" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Output:" id="2OQ-1o-1vp">
<font key="font" metaFont="systemBold" size="12"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KYm-Io-VNv">
<rect key="frame" x="390" y="244" width="72" height="16"/>
<constraints>
<constraint firstAttribute="width" constant="68" id="fOV-38-VqQ"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="0" id="gfS-wb-pFu">
<numberFormatter key="formatter" formatterBehavior="custom10_4" minimumIntegerDigits="0" maximumIntegerDigits="42" id="py5-BY-fQN">
<metadata>
<real key="inspectorSampleValue" value="44"/>
</metadata>
</numberFormatter>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="5xb-MK-C8b">
<rect key="frame" x="410" y="162" width="54" height="18"/>
<buttonCell key="cell" type="check" title="Loop" bezelStyle="regularSquare" imagePosition="right" state="on" inset="2" id="O83-sN-k0z">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="changeShouldLoop:" target="-2" id="lJN-Pe-JWA"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="vKe-ey-hXI" firstAttribute="baseline" secondItem="vj5-qT-JkR" secondAttribute="baseline" id="03u-fe-Q2r"/>
<constraint firstItem="vj5-qT-JkR" firstAttribute="leading" secondItem="Aa9-nc-WHJ" secondAttribute="trailing" constant="9" id="0QT-jZ-rPL"/>
<constraint firstItem="rRH-oS-VV3" firstAttribute="baseline" secondItem="7AB-VA-xL3" secondAttribute="baseline" id="4WU-L2-5TI"/>
<constraint firstItem="3ul-3w-l3S" firstAttribute="trailing" secondItem="bZW-tA-C61" secondAttribute="trailing" constant="-2" id="75o-B9-UmY"/>
<constraint firstItem="vj5-qT-JkR" firstAttribute="baseline" secondItem="Aa9-nc-WHJ" secondAttribute="baseline" id="8ia-fE-3Ej"/>
<constraint firstItem="Lz1-Gs-1lD" firstAttribute="top" secondItem="5xb-MK-C8b" secondAttribute="bottom" constant="18" id="CG6-jk-Mmj"/>
<constraint firstAttribute="bottom" secondItem="Lz1-Gs-1lD" secondAttribute="bottom" id="Cdp-xg-Udu"/>
<constraint firstItem="0eT-7c-7fJ" firstAttribute="leading" secondItem="2Ma-jj-U3z" secondAttribute="trailing" constant="11" id="F4y-lz-2p6"/>
<constraint firstItem="7AB-VA-xL3" firstAttribute="top" secondItem="OQp-Lr-dlS" secondAttribute="bottom" constant="9" id="GbY-7Z-81V"/>
<constraint firstItem="Lz1-Gs-1lD" firstAttribute="leading" secondItem="Xpo-HP-Ost" secondAttribute="leading" id="HW1-t3-mGg"/>
<constraint firstItem="OQp-Lr-dlS" firstAttribute="leading" secondItem="2Ma-jj-U3z" secondAttribute="leading" id="Ira-0b-xzU"/>
<constraint firstItem="rRH-oS-VV3" firstAttribute="baseline" secondItem="3ul-3w-l3S" secondAttribute="baseline" id="KOD-cZ-e52"/>
<constraint firstItem="CFP-v0-TzQ" firstAttribute="baseline" secondItem="Fw5-pm-4w0" secondAttribute="baseline" id="PbC-KG-EzE"/>
<constraint firstItem="2Ma-jj-U3z" firstAttribute="leading" secondItem="Xpo-HP-Ost" secondAttribute="leading" constant="18" id="PiQ-KC-eta"/>
<constraint firstItem="Fw5-pm-4w0" firstAttribute="top" secondItem="7AB-VA-xL3" secondAttribute="bottom" constant="9" id="SPP-F6-chs"/>
<constraint firstItem="vj5-qT-JkR" firstAttribute="trailing" secondItem="CFP-v0-TzQ" secondAttribute="trailing" id="URd-7z-JBO"/>
<constraint firstAttribute="trailing" secondItem="5xb-MK-C8b" secondAttribute="trailing" constant="18" id="WdY-l2-cmp"/>
<constraint firstItem="RRH-G6-xkQ" firstAttribute="leading" secondItem="Xpo-HP-Ost" secondAttribute="leading" constant="18" id="WiW-CU-B7N"/>
<constraint firstAttribute="trailing" secondItem="Lz1-Gs-1lD" secondAttribute="trailing" id="ay9-Mt-iFx"/>
<constraint firstItem="rRH-oS-VV3" firstAttribute="leading" secondItem="CFP-v0-TzQ" secondAttribute="leading" id="cWn-4f-E04"/>
<constraint firstItem="Fw5-pm-4w0" firstAttribute="leading" secondItem="Aa9-nc-WHJ" secondAttribute="leading" id="cnU-xS-2CO"/>
<constraint firstItem="KYm-Io-VNv" firstAttribute="leading" secondItem="3ul-3w-l3S" secondAttribute="leading" id="dac-nA-d4U"/>
<constraint firstItem="0LV-Bi-dGz" firstAttribute="top" secondItem="RRH-G6-xkQ" secondAttribute="bottom" constant="9" id="dnZ-Rx-iiV"/>
<constraint firstItem="Aa9-nc-WHJ" firstAttribute="top" secondItem="Fw5-pm-4w0" secondAttribute="bottom" constant="9" id="fc6-dV-Lxf"/>
<constraint firstItem="vKe-ey-hXI" firstAttribute="leading" secondItem="vj5-qT-JkR" secondAttribute="trailing" constant="8" symbolic="YES" id="fuB-es-weU"/>
<constraint firstItem="2Ma-jj-U3z" firstAttribute="top" secondItem="Xpo-HP-Ost" secondAttribute="top" constant="18" id="hDY-vI-eWO"/>
<constraint firstItem="OQp-Lr-dlS" firstAttribute="trailing" secondItem="2Ma-jj-U3z" secondAttribute="trailing" id="hXB-Gp-9wN"/>
<constraint firstAttribute="trailing" secondItem="bZW-tA-C61" secondAttribute="trailing" constant="18" id="iUL-br-ASL"/>
<constraint firstItem="OQp-Lr-dlS" firstAttribute="top" secondItem="bZW-tA-C61" secondAttribute="top" id="kny-zR-hiF"/>
<constraint firstItem="Lz1-Gs-1lD" firstAttribute="top" secondItem="0LV-Bi-dGz" secondAttribute="bottom" constant="18" id="l6M-H0-bYA"/>
<constraint firstItem="7AB-VA-xL3" firstAttribute="leading" secondItem="OQp-Lr-dlS" secondAttribute="leading" id="omq-Zw-Gvk"/>
<constraint firstItem="KYm-Io-VNv" firstAttribute="baseline" secondItem="CFP-v0-TzQ" secondAttribute="baseline" id="q8e-0e-Xqt"/>
<constraint firstItem="0eT-7c-7fJ" firstAttribute="top" secondItem="2Ma-jj-U3z" secondAttribute="top" id="snu-Ma-cHX"/>
<constraint firstItem="OQp-Lr-dlS" firstAttribute="top" secondItem="2Ma-jj-U3z" secondAttribute="bottom" constant="12" symbolic="YES" id="tkR-bR-msf"/>
<constraint firstItem="0LV-Bi-dGz" firstAttribute="leading" secondItem="Xpo-HP-Ost" secondAttribute="leading" constant="18" id="tmm-8d-ldM"/>
<constraint firstItem="3ul-3w-l3S" firstAttribute="leading" secondItem="rRH-oS-VV3" secondAttribute="trailing" constant="8" id="uF6-oM-5lN"/>
<constraint firstItem="Fw5-pm-4w0" firstAttribute="leading" secondItem="7AB-VA-xL3" secondAttribute="leading" id="vNA-c3-Gcy"/>
<constraint firstItem="RRH-G6-xkQ" firstAttribute="top" secondItem="Aa9-nc-WHJ" secondAttribute="bottom" constant="9" id="w92-Np-SYg"/>
<constraint firstItem="rRH-oS-VV3" firstAttribute="trailing" secondItem="CFP-v0-TzQ" secondAttribute="trailing" id="wdS-Vt-caT"/>
<constraint firstItem="vj5-qT-JkR" firstAttribute="leading" secondItem="CFP-v0-TzQ" secondAttribute="leading" id="wek-S9-BzW"/>
<constraint firstItem="Lz1-Gs-1lD" firstAttribute="leading" secondItem="Xpo-HP-Ost" secondAttribute="leading" id="Edu-Ye-wV8"/>
<constraint firstAttribute="bottom" secondItem="Lz1-Gs-1lD" secondAttribute="bottom" id="UV6-Xh-8m0"/>
<constraint firstItem="Lz1-Gs-1lD" firstAttribute="top" secondItem="Xpo-HP-Ost" secondAttribute="top" id="b4I-Py-1Kt"/>
<constraint firstAttribute="trailing" secondItem="Lz1-Gs-1lD" secondAttribute="trailing" id="ges-aT-5L1"/>
</constraints>
<point key="canvasLocation" x="191" y="409"/>
</customView>
@@ -24,6 +24,8 @@
66755AEB1B3B79230013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 66755AD61B3B79230013E67E /* TPCircularBuffer.c */; };
66755AEC1B3B79230013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 66755AD91B3B79230013E67E /* CHANGELOG */; };
66755AED1B3B79230013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 66755ADA1B3B79230013E67E /* VERSION */; };
667EEA5D1B51EFB400D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA5C1B51EFB400D57FB2 /* EZAudioFFT.m */; };
667EEA6E1B51F0E600D57FB2 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 667EEA6D1B51F0E600D57FB2 /* Accelerate.framework */; };
94056E0D185BB3D800EB94BA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056E0C185BB3D800EB94BA /* Cocoa.framework */; };
94056E17185BB3D800EB94BA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94056E15185BB3D800EB94BA /* InfoPlist.strings */; };
94056E19185BB3D800EB94BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 94056E18185BB3D800EB94BA /* main.m */; };
@@ -89,6 +91,9 @@
66755AD71B3B79230013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
66755AD91B3B79230013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
66755ADA1B3B79230013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA5B1B51EFB400D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA5C1B51EFB400D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
667EEA6D1B51F0E600D57FB2 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
94056E09185BB3D800EB94BA /* EZAudioRecordExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioRecordExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
94056E0C185BB3D800EB94BA /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
94056E0F185BB3D800EB94BA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@@ -125,6 +130,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
667EEA6E1B51F0E600D57FB2 /* Accelerate.framework in Frameworks */,
941D71AA186298AA007D52D8 /* AVFoundation.framework in Frameworks */,
94056E70185BB42100EB94BA /* QuartzCore.framework in Frameworks */,
94056E6E185BB41900EB94BA /* CoreAudio.framework in Frameworks */,
@@ -157,6 +163,8 @@
66755ABB1B3B79220013E67E /* EZAudioDevice.m */,
66755ABC1B3B79220013E67E /* EZAudioDisplayLink.h */,
66755ABD1B3B79220013E67E /* EZAudioDisplayLink.m */,
667EEA5B1B51EFB400D57FB2 /* EZAudioFFT.h */,
667EEA5C1B51EFB400D57FB2 /* EZAudioFFT.m */,
66755ABE1B3B79220013E67E /* EZAudioFile.h */,
66755ABF1B3B79220013E67E /* EZAudioFile.m */,
66755AC01B3B79220013E67E /* EZAudioFloatConverter.h */,
@@ -218,6 +226,7 @@
94056E0B185BB3D800EB94BA /* Frameworks */ = {
isa = PBXGroup;
children = (
667EEA6D1B51F0E600D57FB2 /* Accelerate.framework */,
941D71A9186298AA007D52D8 /* AVFoundation.framework */,
94056E6F185BB42100EB94BA /* QuartzCore.framework */,
94056E6D185BB41900EB94BA /* CoreAudio.framework */,
@@ -393,6 +402,7 @@
66755AE21B3B79230013E67E /* EZAudioPlayer.m in Sources */,
94056E74185BB44200EB94BA /* RecordViewController.m in Sources */,
66755AE41B3B79230013E67E /* EZAudioPlotGL.m in Sources */,
667EEA5D1B51EFB400D57FB2 /* EZAudioFFT.m in Sources */,
66755ADF1B3B79230013E67E /* EZAudioFile.m in Sources */,
66755AE81B3B79230013E67E /* EZOutput.m in Sources */,
66755AE61B3B79230013E67E /* EZAudioUtilities.m in Sources */,
@@ -28,8 +28,7 @@
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
{
// Swap in our view controller in the window's content view
self.recordViewController = [[RecordViewController alloc] init];
// Resize view controller to content view's current size
@@ -1,100 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4439" systemVersion="13A451" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4439"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<action selector="orderFrontStandardAboutPanel:" destination="58" id="142"/>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder">
<connections>
<action selector="alignCenter:" destination="499" id="518"/>
<action selector="alignJustified:" destination="500" id="523"/>
<action selector="alignLeft:" destination="498" id="524"/>
<action selector="alignRight:" destination="501" id="521"/>
<action selector="arrangeInFront:" destination="5" id="39"/>
<action selector="capitalizeWord:" destination="466" id="467"/>
<action selector="centerSelectionInVisibleArea:" destination="210" id="245"/>
<action selector="checkSpelling:" destination="201" id="225"/>
<action selector="clearRecentDocuments:" destination="126" id="127"/>
<action selector="copy:" destination="197" id="224"/>
<action selector="copyFont:" destination="403" id="428"/>
<action selector="copyRuler:" destination="506" id="522"/>
<action selector="cut:" destination="199" id="228"/>
<action selector="delete:" destination="202" id="235"/>
<action selector="hide:" destination="134" id="367"/>
<action selector="hideOtherApplications:" destination="145" id="368"/>
<action selector="loosenKerning:" destination="419" id="435"/>
<action selector="lowerBaseline:" destination="410" id="427"/>
<action selector="lowercaseWord:" destination="465" id="468"/>
<action selector="makeBaseWritingDirectionLeftToRight:" destination="511" id="526"/>
<action selector="makeBaseWritingDirectionNatural:" destination="510" id="525"/>
<action selector="makeBaseWritingDirectionRightToLeft:" destination="512" id="527"/>
<action selector="makeTextWritingDirectionLeftToRight:" destination="516" id="529"/>
<action selector="makeTextWritingDirectionNatural:" destination="515" id="528"/>
<action selector="makeTextWritingDirectionRightToLeft:" destination="517" id="530"/>
<action selector="newDocument:" destination="82" id="373"/>
<action selector="openDocument:" destination="72" id="374"/>
<action selector="orderFrontColorPanel:" destination="401" id="433"/>
<action selector="orderFrontSubstitutionsPanel:" destination="457" id="458"/>
<action selector="paste:" destination="203" id="226"/>
<action selector="pasteAsPlainText:" destination="485" id="486"/>
<action selector="pasteFont:" destination="404" id="436"/>
<action selector="pasteRuler:" destination="507" id="519"/>
<action selector="performClose:" destination="73" id="193"/>
<action selector="performFindPanelAction:" destination="209" id="241"/>
<action selector="performFindPanelAction:" destination="208" id="487"/>
<action selector="performFindPanelAction:" destination="213" id="488"/>
<action selector="performFindPanelAction:" destination="221" id="489"/>
<action selector="performFindPanelAction:" destination="534" id="535"/>
<action selector="performMiniaturize:" destination="23" id="37"/>
<action selector="performZoom:" destination="239" id="240"/>
<action selector="print:" destination="78" id="86"/>
<action selector="raiseBaseline:" destination="409" id="426"/>
<action selector="redo:" destination="215" id="231"/>
<action selector="revertDocumentToSaved:" destination="112" id="364"/>
<action selector="runPageLayout:" destination="77" id="87"/>
<action selector="runToolbarCustomizationPalette:" destination="298" id="365"/>
<action selector="saveDocument:" destination="75" id="362"/>
<action selector="selectAll:" destination="198" id="232"/>
<action selector="showGuessPanel:" destination="204" id="230"/>
<action selector="showHelp:" destination="492" id="493"/>
<action selector="startSpeaking:" destination="196" id="233"/>
<action selector="stopSpeaking:" destination="195" id="227"/>
<action selector="subscript:" destination="408" id="429"/>
<action selector="superscript:" destination="407" id="430"/>
<action selector="tightenKerning:" destination="418" id="431"/>
<action selector="toggleAutomaticDashSubstitution:" destination="460" id="461"/>
<action selector="toggleAutomaticLinkDetection:" destination="354" id="357"/>
<action selector="toggleAutomaticQuoteSubstitution:" destination="351" id="356"/>
<action selector="toggleAutomaticSpellingCorrection:" destination="454" id="456"/>
<action selector="toggleAutomaticTextReplacement:" destination="462" id="463"/>
<action selector="toggleContinuousSpellChecking:" destination="219" id="222"/>
<action selector="toggleGrammarChecking:" destination="346" id="347"/>
<action selector="toggleRuler:" destination="505" id="520"/>
<action selector="toggleSmartInsertDelete:" destination="350" id="355"/>
<action selector="toggleToolbarShown:" destination="297" id="366"/>
<action selector="turnOffKerning:" destination="417" id="441"/>
<action selector="turnOffLigatures:" destination="413" id="440"/>
<action selector="underline:" destination="392" id="432"/>
<action selector="undo:" destination="207" id="223"/>
<action selector="unhideAllApplications:" destination="150" id="370"/>
<action selector="unscript:" destination="406" id="437"/>
<action selector="uppercaseWord:" destination="452" id="464"/>
<action selector="useAllLigatures:" destination="414" id="434"/>
<action selector="useStandardKerning:" destination="416" id="438"/>
<action selector="useStandardLigatures:" destination="412" id="439"/>
</connections>
</customObject>
<customObject id="-3" userLabel="Application">
<connections>
<action selector="terminate:" destination="136" id="449"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="EZAudioRecordExample" id="56">
@@ -102,6 +19,9 @@
<items>
<menuItem title="About EZAudioRecordExample" 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"/>
@@ -116,95 +36,211 @@
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide EZAudioRecordExample" keyEquivalent="h" id="134"/>
<menuItem title="Hide EZAudioRecordExample" 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 title="Show All" id="150"/>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit EZAudioRecordExample" keyEquivalent="q" id="136"/>
<menuItem title="Quit EZAudioRecordExample" 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"/>
<menuItem title="Open…" keyEquivalent="o" id="72"/>
<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"/>
<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"/>
<menuItem title="Save…" keyEquivalent="s" id="75"/>
<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>
<menuItem title="Print…" keyEquivalent="p" id="78"/>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207"/>
<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"/>
<menuItem title="Copy" keyEquivalent="c" id="197"/>
<menuItem title="Paste" keyEquivalent="v" id="203"/>
<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 title="Delete" id="202"/>
<menuItem title="Select All" keyEquivalent="a" id="198"/>
<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"/>
<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 Next" tag="2" keyEquivalent="g" id="208"/>
<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>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210"/>
</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"/>
<menuItem title="Check Document Now" keyEquivalent=";" id="201"/>
<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"/>
<menuItem title="Check Grammar With Spelling" id="346"/>
<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>
@@ -214,18 +250,38 @@
<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"/>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351"/>
<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>
@@ -236,12 +292,21 @@
<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>
@@ -249,8 +314,16 @@
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196"/>
<menuItem title="Stop Speaking" id="195"/>
<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>
@@ -265,13 +338,37 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389"/>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390"/>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391"/>
<menuItem title="Underline" keyEquivalent="u" id="392"/>
<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"/>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395"/>
<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"/>
@@ -279,15 +376,27 @@
<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>
@@ -298,12 +407,21 @@
<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>
@@ -314,30 +432,55 @@
<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"/>
<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>
@@ -346,12 +489,27 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498"/>
<menuItem title="Center" keyEquivalent="|" id="499"/>
<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 title="Align Right" keyEquivalent="}" id="501"/>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
@@ -363,14 +521,23 @@
<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">
@@ -379,14 +546,23 @@
<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>
@@ -394,12 +570,21 @@
<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>
@@ -412,20 +597,39 @@
<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>
<menuItem title="Customize Toolbar…" id="298"/>
</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"/>
<menuItem title="Zoom" id="239"/>
<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"/>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
@@ -433,17 +637,21 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="EZAudioRecordExample Help" keyEquivalent="?" id="492"/>
<menuItem title="EZAudioRecordExample Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="EZAudioRecordExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="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="2560" height="1418"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
@@ -454,14 +662,6 @@
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager">
<connections>
<action selector="addFontTrait:" destination="390" id="421"/>
<action selector="addFontTrait:" destination="391" id="422"/>
<action selector="modifyFont:" destination="395" id="423"/>
<action selector="modifyFont:" destination="394" id="425"/>
<action selector="orderFrontFontPanel:" destination="389" id="424"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -28,51 +28,116 @@
// Import EZAudio header
#import "EZAudio.h"
// Import AVFoundation to play the file (will save EZAudioFile and EZOutput for separate example)
#import <AVFoundation/AVFoundation.h>
// By default this will record a file to /Users/YOUR_USERNAME/Documents/test.caf
#define kAudioFilePath [NSString stringWithFormat:@"%@%@",NSHomeDirectory(),@"/Documents/test.m4a"]
//------------------------------------------------------------------------------
#pragma mark - RecordViewController
//------------------------------------------------------------------------------
/**
We will allow this view controller to act as an EZMicrophoneDelegate. This is how we listen for the microphone callback.
*/
@interface RecordViewController : NSViewController <EZMicrophoneDelegate,AVAudioPlayerDelegate>
@interface RecordViewController : NSViewController <EZAudioPlayerDelegate,
EZMicrophoneDelegate,
EZRecorderDelegate>
/**
The label used to display the current time for recording/playback in the top left
*/
@property (nonatomic, weak) IBOutlet NSTextField *currentTimeLabel;
//------------------------------------------------------------------------------
/**
Use a OpenGL based plot to visualize the data coming in
*/
@property (nonatomic,weak) IBOutlet EZAudioPlotGL *audioPlot;
@property (nonatomic, weak) IBOutlet EZAudioPlotGL *recordingAudioPlot;
//------------------------------------------------------------------------------
/**
A flag indicating whether we are recording or not
*/
@property (nonatomic,assign) BOOL isRecording;
@property (nonatomic, assign) BOOL isRecording;
//------------------------------------------------------------------------------
/**
The microphone component
*/
@property (nonatomic,strong) EZMicrophone *microphone;
@property (nonatomic, strong) EZMicrophone *microphone;
//------------------------------------------------------------------------------
/**
The switch used to toggle the microphone on/off
*/
@property (nonatomic, weak) IBOutlet NSButton *microphoneSwitch;
//------------------------------------------------------------------------------
/**
The audio player that will play the recorded file
*/
@property (nonatomic, strong) EZAudioPlayer *player;
//------------------------------------------------------------------------------
/**
The recorder component
*/
@property (nonatomic,strong) EZRecorder *recorder;
@property (nonatomic, strong) EZRecorder *recorder;
//------------------------------------------------------------------------------
/**
The second audio plot used on the top right to display the current playing audio
*/
@property (nonatomic, weak) IBOutlet EZAudioPlot *playingAudioPlot;
//------------------------------------------------------------------------------
/**
The button the user taps to play the recorded audio file
*/
@property (nonatomic, weak) IBOutlet NSButton *playButton;
//------------------------------------------------------------------------------
/**
The label used to display the audio player play state
*/
@property (nonatomic, weak) IBOutlet NSTextField *playingStateLabel;
//------------------------------------------------------------------------------
/**
The switch used to toggle the recording on/off
*/
@property (nonatomic, weak) IBOutlet NSButton *recordSwitch;
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
/**
Stops the recorder and starts playing whatever has been recorded.
*/
-(IBAction)playFile:(id)sender;
- (IBAction)playFile:(id)sender;
//------------------------------------------------------------------------------
/**
Toggles the microphone on and off. When the microphone is on it will send its delegate (aka this view controller) the audio data in various ways (check out the EZMicrophoneDelegate documentation for more details);
*/
-(IBAction)toggleMicrophone:(id)sender;
- (IBAction)toggleMicrophone:(id)sender;
//------------------------------------------------------------------------------
/**
Toggles the microphone on and off. When the microphone is on it will send its delegate (aka this view controller) the audio data in various ways (check out the EZMicrophoneDelegate documentation for more details);
*/
-(IBAction)toggleRecording:(id)sender;
- (IBAction)toggleRecording:(id)sender;
@end
@@ -25,12 +25,9 @@
#import "RecordViewController.h"
@interface RecordViewController ()
@property (nonatomic,strong) AVAudioPlayer *audioPlayer;
@property (nonatomic,weak) IBOutlet NSButton *microphoneToggle;
@property (nonatomic,weak) IBOutlet NSButton *playButton;
@property (nonatomic,weak) IBOutlet NSButton *recordingToggle;
@end
//------------------------------------------------------------------------------
#pragma mark - RecordViewController (Implementation)
//------------------------------------------------------------------------------
@implementation RecordViewController
@@ -38,52 +35,106 @@
#pragma mark - Customize the Audio Plot
//------------------------------------------------------------------------------
-(void)awakeFromNib
- (void)awakeFromNib
{
/*
Customizing the audio plot's look
*/
// Background color
self.audioPlot.backgroundColor = [NSColor colorWithCalibratedRed: 0.984 green: 0.71 blue: 0.365 alpha: 1];
// Waveform color
self.audioPlot.color = [NSColor colorWithCalibratedRed: 1.000 green: 1.000 blue: 1.000 alpha: 1];
// Plot type
self.audioPlot.plotType = EZPlotTypeRolling;
// Fill
self.audioPlot.shouldFill = YES;
// Mirror
self.audioPlot.shouldMirror = YES;
//
// Customizing the audio plot that'll show the current microphone input/recording
//
self.recordingAudioPlot.backgroundColor = [NSColor colorWithRed: 0.984 green: 0.71 blue: 0.365 alpha: 1];
self.recordingAudioPlot.color = [NSColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.recordingAudioPlot.plotType = EZPlotTypeRolling;
self.recordingAudioPlot.shouldFill = YES;
self.recordingAudioPlot.shouldMirror = YES;
//
// Customizing the audio plot that'll show the playback
//
self.playingAudioPlot.color = [NSColor whiteColor];
self.playingAudioPlot.plotType = EZPlotTypeRolling;
self.playingAudioPlot.shouldFill = YES;
self.playingAudioPlot.shouldMirror = YES;
self.playingAudioPlot.gain = 2.5f;
// Create an instance of the microphone and tell it to use this view controller instance as the delegate
self.microphone = [EZMicrophone microphoneWithDelegate:self];
self.player = [EZAudioPlayer audioPlayerWithDelegate:self];
//
// Initialize UI components
//
[self setTitle:@"Microphone On" forButton:self.microphoneSwitch];
[self setTitle:@"Not Recording" forButton:self.recordSwitch];
self.playingStateLabel.stringValue = @"Not Playing";
self.playButton.enabled = NO;
//
// Setup notifications
//
[self setupNotifications];
//
// Start the microphone
//
[self.microphone startFetchingAudio];
}
// Configure the play button
[self.playButton setHidden:YES];
/*
Start the microphone
*/
self.microphone = [EZMicrophone microphoneWithDelegate:self startsImmediately:YES];
//------------------------------------------------------------------------------
- (void)setupNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerDidChangePlayState:)
name:EZAudioPlayerDidChangePlayStateNotification
object:self.player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerDidReachEndOfFile:)
name:EZAudioPlayerDidReachEndOfFileNotification
object:self.player];
}
//------------------------------------------------------------------------------
#pragma mark - Notifications
//------------------------------------------------------------------------------
- (void)playerDidChangePlayState:(NSNotification *)notification
{
EZAudioPlayer *player = [notification object];
BOOL isPlaying = [player isPlaying];
if (isPlaying)
{
self.recorder.delegate = nil;
}
self.playingStateLabel.stringValue = isPlaying ? @"Playing" : @"Not Playing";
self.playingAudioPlot.hidden = !isPlaying;
}
//------------------------------------------------------------------------------
- (void)playerDidReachEndOfFile:(NSNotification *)notification
{
[self.playingAudioPlot clear];
}
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
-(void)playFile:(id)sender
- (void)playFile:(id)sender
{
//
// Update microphone state
//
[self.microphone stopFetchingAudio];
self.microphoneToggle.state = NSOffState;
[self.microphoneToggle setEnabled:NO];
//
// Update recording state
//
self.isRecording = NO;
self.recordingToggle.state = NSOffState;
[self.recordingToggle setEnabled:NO];
[self setTitle:@"Not Recording" forButton:self.recordSwitch];
self.recordSwitch.state = NSOffState;
//
// Close the audio file
//
@@ -92,122 +143,157 @@
[self.recorder closeAudioFile];
}
//
// Create audio player
//
if (self.audioPlayer)
{
if (self.audioPlayer.playing) [self.audioPlayer stop];
self.audioPlayer = nil;
}
NSError *err;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:kAudioFilePath]
error:&err];
EZAudioFile *audioFile = [EZAudioFile audioFileWithURL:[NSURL fileURLWithPath:kAudioFilePath]];
[self.player playAudioFile:audioFile];
}
//------------------------------------------------------------------------------
- (void)toggleMicrophone:(id)sender
{
[self.player pause];
[self.audioPlayer play];
self.audioPlayer.delegate = self;
}
//------------------------------------------------------------------------------
-(void)toggleMicrophone:(id)sender
{
switch([sender state])
NSInteger state = [(NSButton *)sender state];
if (state == NSOffState)
{
case NSOffState:
[self.microphone stopFetchingAudio];
break;
case NSOnState:
[self.microphone startFetchingAudio];
break;
default:
break;
[self.microphone stopFetchingAudio];
}
else
{
[self.microphone startFetchingAudio];
}
}
//------------------------------------------------------------------------------
-(void)toggleRecording:(id)sender
- (void)toggleRecording:(id)sender
{
[self.playButton setHidden:NO];
switch( [sender state])
[self.player pause];
NSInteger state = [(NSButton *)sender state];
if (state == NSOnState)
{
case NSOffState:
[self.recorder closeAudioFile];
break;
case NSOnState:
/*
Create the recorder
*/
self.recorder = [EZRecorder recorderWithDestinationURL:[NSURL fileURLWithPath:kAudioFilePath]
sourceFormat:[self.microphone audioStreamBasicDescription]
destinationFileType:EZRecorderFileTypeM4A];
break;
default:
break;
//
// Create the recorder
//
[self.microphone startFetchingAudio];
self.recorder = [EZRecorder recorderWithURL:[NSURL fileURLWithPath:kAudioFilePath]
clientFormat:[self.microphone audioStreamBasicDescription]
fileType:EZRecorderFileTypeM4A
delegate:self];
self.playButton.enabled = YES;
}
self.isRecording = (BOOL)[sender state];
self.isRecording = state;
NSString *title = self.isRecording ? @"Recording" : @"Not Recording";
[self setTitle:title forButton:self.recordSwitch];
}
//------------------------------------------------------------------------------
#pragma mark - EZMicrophoneDelegate
//------------------------------------------------------------------------------
- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying
{
self.microphoneSwitch.state = isPlaying;
NSString *title = isPlaying ? @"Microphone On" : @"Microphone Off";
[self setTitle:title forButton:self.microphoneSwitch];
}
//------------------------------------------------------------------------------
#warning Thread Safety
// Note that any callback that provides streamed audio data (like streaming microphone input) happens on a separate audio thread that should not be blocked. When we feed audio data into any of the UI components we need to explicity create a GCD block on the main thread to properly get the UI to work.
-(void)microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
- (void) microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
{
// Getting audio data as an array of float buffer arrays. What does that mean? Because the audio is coming in as a stereo signal the data is split into a left and right channel. So buffer[0] corresponds to the float* data for the left channel while buffer[1] corresponds to the float* data for the right channel.
// See the Thread Safety warning above, but in a nutshell these callbacks happen on a separate audio thread. We wrap any UI updating in a GCD block on the main thread to avoid blocking that audio flow.
// Getting audio data as an array of float buffer arrays. What does that mean? Because the audio is coming in as a stereo signal the data is split into a left and right channel. So buffer[0] corresponds to the float* data for the left channel while buffer[1] corresponds to the float* data for the right channel.
// See the Thread Safety warning above, but in a nutshell these callbacks happen on a separate audio thread. We wrap any UI updating in a GCD block on the main thread to avoid blocking that audio flow.
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(),^{
// All the audio plot needs is the buffer data (float*) and the size. Internally the audio plot will handle all the drawing related code, history management, and freeing its own resources. Hence, one badass line of code gets you a pretty plot :)
[weakSelf.audioPlot updateBuffer:buffer[0]
withBufferSize:bufferSize];
dispatch_async(dispatch_get_main_queue(), ^{
// All the audio plot needs is the buffer data (float*) and the size. Internally the audio plot will handle all the drawing related code, history management, and freeing its own resources. Hence, one badass line of code gets you a pretty plot :)
[weakSelf.recordingAudioPlot updateBuffer:buffer[0]
withBufferSize:bufferSize];
});
}
//------------------------------------------------------------------------------
// Append the microphone data coming as a AudioBufferList with the specified buffer size to the recorder
-(void) microphone:(EZMicrophone *)microphone
- (void) microphone:(EZMicrophone *)microphone
hasBufferList:(AudioBufferList *)bufferList
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
{
// Getting audio data as a buffer list that can be directly fed into the EZRecorder. This is happening on the audio thread - any UI updating needs a GCD main queue block.
// Getting audio data as a buffer list that can be directly fed into the EZRecorder. This is happening on the audio thread - any UI updating needs a GCD main queue block. This will keep appending data to the tail of the audio file.
if (self.isRecording)
{
[self.recorder appendDataFromBufferList:bufferList
withBufferSize:bufferSize];
}
}
}
//------------------------------------------------------------------------------
#pragma mark - AVAudioPlayerDelegate
#pragma mark - EZRecorderDelegate
//------------------------------------------------------------------------------
/*
Occurs when the audio player instance completes playback
*/
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
successfully:(BOOL)flag
- (void)recorderDidClose:(EZRecorder *)recorder
{
// Update microphone state
self.microphoneToggle.state = NSOnState;
[self.microphoneToggle setEnabled:YES];
[self.microphone startFetchingAudio];
// Update recording state
self.isRecording = NO;
self.recordingToggle.state = NSOffState;
[self.recordingToggle setEnabled:YES];
recorder.delegate = nil;
}
//------------------------------------------------------------------------------
- (void)recorderUpdatedCurrentTime:(EZRecorder *)recorder
{
__weak typeof (self) weakSelf = self;
NSString *formattedCurrentTime = [recorder formattedCurrentTime];
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.currentTimeLabel.stringValue = formattedCurrentTime;
});
}
//------------------------------------------------------------------------------
#pragma mark - EZAudioPlayerDelegate
//------------------------------------------------------------------------------
- (void) audioPlayer:(EZAudioPlayer *)audioPlayer
playedAudio:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
inAudioFile:(EZAudioFile *)audioFile
{
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.playingAudioPlot updateBuffer:buffer[0]
withBufferSize:bufferSize];
});
}
//------------------------------------------------------------------------------
- (void)audioPlayer:(EZAudioPlayer *)audioPlayer
updatedPosition:(SInt64)framePosition
inAudioFile:(EZAudioFile *)audioFile
{
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.currentTimeLabel.stringValue = [audioPlayer formattedCurrentTime];
});
}
//------------------------------------------------------------------------------
#pragma mark - Utility
//------------------------------------------------------------------------------
- (void)setTitle:(NSString *)title forButton:(NSButton *)button
{
NSDictionary *attributes = @{ NSForegroundColorAttributeName : [NSColor whiteColor] };
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title
attributes:attributes];
button.attributedTitle = attributedTitle;
button.attributedAlternateTitle = attributedTitle;
}
@end
@@ -1,79 +1,116 @@
<?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="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment version="1070" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="RecordViewController">
<connections>
<outlet property="audioPlot" destination="dEs-hA-819" id="iGa-BH-xLn"/>
<outlet property="microphoneToggle" destination="642-4u-aBm" id="FYB-Cp-aPB"/>
<outlet property="playButton" destination="y4R-NE-icG" id="1FP-aQ-BcB"/>
<outlet property="recordingToggle" destination="fdr-L4-Y6i" id="dYX-uf-6YS"/>
<outlet property="currentTimeLabel" destination="HxF-TY-fDR" id="zwj-XE-ACe"/>
<outlet property="microphoneSwitch" destination="642-4u-aBm" id="AEv-nm-gLS"/>
<outlet property="playButton" destination="y4R-NE-icG" id="kHv-iM-mCt"/>
<outlet property="playingAudioPlot" destination="1yQ-Hd-JGR" id="Hdj-Ve-A6A"/>
<outlet property="playingStateLabel" destination="y9d-HG-0Rl" id="YXg-yy-Q9t"/>
<outlet property="recordSwitch" destination="fdr-L4-Y6i" id="Rqe-gC-lfh"/>
<outlet property="recordingAudioPlot" destination="dEs-hA-819" id="ACe-8h-ags"/>
<outlet property="view" destination="178-e9-GIn" id="bPz-Je-f18"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="178-e9-GIn">
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="dEs-hA-819" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="42" width="480" height="230"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView>
<button misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="642-4u-aBm">
<rect key="frame" x="18" y="14" width="119" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="HxF-TY-fDR">
<rect key="frame" x="16" y="193" width="85" height="39"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="00:00" id="Lsu-38-RnW">
<font key="font" size="32" name="HelveticaNeue-Light"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1yQ-Hd-JGR" customClass="EZAudioPlot">
<rect key="frame" x="108" y="193" width="354" height="39"/>
<constraints>
<constraint firstAttribute="height" constant="39" id="Cmv-Of-yxB"/>
</constraints>
</customView>
<button translatesAutoresizingMaskIntoConstraints="NO" id="642-4u-aBm">
<rect key="frame" x="16" y="39" width="119" height="18"/>
<constraints>
<constraint firstAttribute="width" constant="115" id="jzA-c9-gss"/>
</constraints>
<buttonCell key="cell" type="check" title="Microphone Off" alternateTitle="Microphone On" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="WpM-g2-QmU">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleMicrophone:" target="-2" id="xOT-qg-D3j"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="fdr-L4-Y6i">
<rect key="frame" x="16" y="16" width="113" height="18"/>
<constraints>
<constraint firstAttribute="width" constant="109" id="XVw-ku-8Kp"/>
</constraints>
<buttonCell key="cell" type="check" title="Not Recording" alternateTitle="Recording" bezelStyle="regularSquare" imagePosition="left" inset="2" id="j1l-ue-yI3">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleRecording:" target="-2" id="WKw-uD-CBI"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="y4R-NE-icG">
<rect key="frame" x="12" y="57" width="65" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="53" id="eH3-f2-ls9"/>
</constraints>
<buttonCell key="cell" type="push" title="Play" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="XoV-qX-N9x">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="playFile:" target="-2" id="jrd-yg-pvq"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="y9d-HG-0Rl">
<rect key="frame" x="76" y="66" width="75" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Not Playing" id="pde-yf-Cac">
<font key="font" metaFont="system"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="14" id="DDP-K1-hjt"/>
<constraint firstItem="y9d-HG-0Rl" firstAttribute="leading" secondItem="y4R-NE-icG" secondAttribute="trailing" constant="7" id="5mU-Du-t8h"/>
<constraint firstItem="fdr-L4-Y6i" firstAttribute="leading" secondItem="642-4u-aBm" secondAttribute="leading" id="6HB-Yz-Xlv"/>
<constraint firstItem="642-4u-aBm" firstAttribute="top" secondItem="y4R-NE-icG" secondAttribute="bottom" constant="9" id="Gvt-cc-iCu"/>
<constraint firstItem="1yQ-Hd-JGR" firstAttribute="top" secondItem="dEs-hA-819" secondAttribute="top" constant="40" id="MIg-OC-dHb"/>
<constraint firstItem="1yQ-Hd-JGR" firstAttribute="leading" secondItem="HxF-TY-fDR" secondAttribute="trailing" constant="9" id="Njb-Oj-SUR"/>
<constraint firstItem="HxF-TY-fDR" firstAttribute="leading" secondItem="dEs-hA-819" secondAttribute="leading" constant="18" id="Y42-ar-917"/>
<constraint firstItem="y4R-NE-icG" firstAttribute="leading" secondItem="HxF-TY-fDR" secondAttribute="leading" id="eTn-op-NgF"/>
<constraint firstItem="fdr-L4-Y6i" firstAttribute="top" secondItem="642-4u-aBm" secondAttribute="bottom" constant="9" id="hb4-N7-xjI"/>
<constraint firstItem="HxF-TY-fDR" firstAttribute="top" secondItem="dEs-hA-819" secondAttribute="top" constant="40" id="kI9-mf-kW9"/>
<constraint firstAttribute="trailing" secondItem="1yQ-Hd-JGR" secondAttribute="trailing" constant="18" id="nDj-wc-gcG"/>
<constraint firstAttribute="bottom" secondItem="fdr-L4-Y6i" secondAttribute="bottom" constant="18" id="nGo-GX-HZv"/>
<constraint firstItem="642-4u-aBm" firstAttribute="leading" secondItem="y4R-NE-icG" secondAttribute="leading" id="o9C-CB-nEE"/>
<constraint firstItem="y9d-HG-0Rl" firstAttribute="centerY" secondItem="y4R-NE-icG" secondAttribute="centerY" id="xIG-Gy-XOS"/>
</constraints>
<buttonCell key="cell" type="check" title="Microphone Off" alternateTitle="Microphone On" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="WpM-g2-QmU">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleMicrophone:" target="-2" id="xOT-qg-D3j"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="fdr-L4-Y6i">
<rect key="frame" x="349" y="14" width="113" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Not Recording" alternateTitle="Recording" bezelStyle="regularSquare" imagePosition="left" inset="2" id="j1l-ue-yI3">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleRecording:" target="-2" id="WKw-uD-CBI"/>
</connections>
</button>
<button verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="y4R-NE-icG">
<rect key="frame" x="137" y="6" width="65" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Play" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="XoV-qX-N9x">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="playFile:" target="-2" id="jrd-yg-pvq"/>
</connections>
</button>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="642-4u-aBm" secondAttribute="bottom" constant="16" id="LIb-Ej-46s"/>
<constraint firstAttribute="bottom" secondItem="fdr-L4-Y6i" secondAttribute="bottom" constant="16" id="Pvr-gh-o7q"/>
<constraint firstItem="642-4u-aBm" firstAttribute="top" secondItem="dEs-hA-819" secondAttribute="bottom" constant="12" id="QgB-Ty-AN0"/>
<constraint firstAttribute="bottom" secondItem="y4R-NE-icG" secondAttribute="bottom" constant="13" id="UX6-ts-w3M"/>
<constraint firstItem="y4R-NE-icG" firstAttribute="leading" secondItem="642-4u-aBm" secondAttribute="trailing" constant="8" id="ZbS-5O-fFJ"/>
<constraint firstItem="642-4u-aBm" firstAttribute="leading" secondItem="178-e9-GIn" secondAttribute="leading" constant="20" id="ayr-0v-aOC"/>
<constraint firstAttribute="trailing" secondItem="fdr-L4-Y6i" secondAttribute="trailing" constant="20" id="hk9-I9-9g5"/>
<constraint firstItem="dEs-hA-819" firstAttribute="top" secondItem="178-e9-GIn" secondAttribute="top" id="mv6-AK-Cz4"/>
<constraint firstAttribute="trailing" secondItem="dEs-hA-819" secondAttribute="trailing" id="tqk-1H-SZ4"/>
<constraint firstItem="y4R-NE-icG" firstAttribute="top" secondItem="dEs-hA-819" secondAttribute="bottom" constant="8" id="xzp-cM-xAL"/>
<constraint firstItem="dEs-hA-819" firstAttribute="leading" secondItem="178-e9-GIn" secondAttribute="leading" id="yvm-d3-Fzl"/>
<constraint firstAttribute="trailing" secondItem="dEs-hA-819" secondAttribute="trailing" id="R5V-pX-y9Q"/>
<constraint firstItem="dEs-hA-819" firstAttribute="leading" secondItem="178-e9-GIn" secondAttribute="leading" id="UWT-Ay-DKN"/>
<constraint firstAttribute="bottom" secondItem="dEs-hA-819" secondAttribute="bottom" id="ajJ-h2-gWy"/>
<constraint firstItem="dEs-hA-819" firstAttribute="top" secondItem="178-e9-GIn" secondAttribute="top" id="h1e-yD-I80"/>
</constraints>
</customView>
</objects>
</document>
</document>
@@ -24,6 +24,8 @@
66755B241B3B792A0013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 66755B0F1B3B792A0013E67E /* TPCircularBuffer.c */; };
66755B251B3B792A0013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 66755B121B3B792A0013E67E /* CHANGELOG */; };
66755B261B3B792A0013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 66755B131B3B792A0013E67E /* VERSION */; };
667EEA601B51EFC400D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA5F1B51EFC400D57FB2 /* EZAudioFFT.m */; };
667EEA701B51F0EC00D57FB2 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 667EEA6F1B51F0EC00D57FB2 /* Accelerate.framework */; };
94056E83185BCBC000EB94BA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056E82185BCBC000EB94BA /* Cocoa.framework */; };
94056E8D185BCBC000EB94BA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94056E8B185BCBC000EB94BA /* InfoPlist.strings */; };
94056E8F185BCBC000EB94BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 94056E8E185BCBC000EB94BA /* main.m */; };
@@ -89,6 +91,9 @@
66755B101B3B792A0013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
66755B121B3B792A0013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
66755B131B3B792A0013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA5E1B51EFC400D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA5F1B51EFC400D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
667EEA6F1B51F0EC00D57FB2 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
94056E7F185BCBC000EB94BA /* EZAudioWaveformFromFileExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioWaveformFromFileExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
94056E82185BCBC000EB94BA /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
94056E85185BCBC000EB94BA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@@ -125,6 +130,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
667EEA701B51F0EC00D57FB2 /* Accelerate.framework in Frameworks */,
94056EEB185BCDC500EB94BA /* QuartzCore.framework in Frameworks */,
94056EE7185BCDBF00EB94BA /* AudioToolbox.framework in Frameworks */,
94056EE8185BCDBF00EB94BA /* AudioUnit.framework in Frameworks */,
@@ -156,6 +162,8 @@
66755AF41B3B792A0013E67E /* EZAudioDevice.m */,
66755AF51B3B792A0013E67E /* EZAudioDisplayLink.h */,
66755AF61B3B792A0013E67E /* EZAudioDisplayLink.m */,
667EEA5E1B51EFC400D57FB2 /* EZAudioFFT.h */,
667EEA5F1B51EFC400D57FB2 /* EZAudioFFT.m */,
66755AF71B3B792A0013E67E /* EZAudioFile.h */,
66755AF81B3B792A0013E67E /* EZAudioFile.m */,
66755AF91B3B792A0013E67E /* EZAudioFloatConverter.h */,
@@ -217,6 +225,7 @@
94056E81185BCBC000EB94BA /* Frameworks */ = {
isa = PBXGroup;
children = (
667EEA6F1B51F0EC00D57FB2 /* Accelerate.framework */,
94056EEA185BCDC500EB94BA /* QuartzCore.framework */,
94056EE4185BCDBF00EB94BA /* AudioToolbox.framework */,
94056EE5185BCDBF00EB94BA /* AudioUnit.framework */,
@@ -393,6 +402,7 @@
66755B1B1B3B792A0013E67E /* EZAudioPlayer.m in Sources */,
94056E96185BCBC000EB94BA /* AppDelegate.m in Sources */,
66755B1D1B3B792A0013E67E /* EZAudioPlotGL.m in Sources */,
667EEA601B51EFC400D57FB2 /* EZAudioFFT.m in Sources */,
66755B181B3B792A0013E67E /* EZAudioFile.m in Sources */,
66755B211B3B792A0013E67E /* EZOutput.m in Sources */,
66755B1F1B3B792A0013E67E /* EZAudioUtilities.m in Sources */,
@@ -1,100 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4439" systemVersion="13A451" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4439"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<action selector="orderFrontStandardAboutPanel:" destination="58" id="142"/>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder">
<connections>
<action selector="alignCenter:" destination="499" id="518"/>
<action selector="alignJustified:" destination="500" id="523"/>
<action selector="alignLeft:" destination="498" id="524"/>
<action selector="alignRight:" destination="501" id="521"/>
<action selector="arrangeInFront:" destination="5" id="39"/>
<action selector="capitalizeWord:" destination="466" id="467"/>
<action selector="centerSelectionInVisibleArea:" destination="210" id="245"/>
<action selector="checkSpelling:" destination="201" id="225"/>
<action selector="clearRecentDocuments:" destination="126" id="127"/>
<action selector="copy:" destination="197" id="224"/>
<action selector="copyFont:" destination="403" id="428"/>
<action selector="copyRuler:" destination="506" id="522"/>
<action selector="cut:" destination="199" id="228"/>
<action selector="delete:" destination="202" id="235"/>
<action selector="hide:" destination="134" id="367"/>
<action selector="hideOtherApplications:" destination="145" id="368"/>
<action selector="loosenKerning:" destination="419" id="435"/>
<action selector="lowerBaseline:" destination="410" id="427"/>
<action selector="lowercaseWord:" destination="465" id="468"/>
<action selector="makeBaseWritingDirectionLeftToRight:" destination="511" id="526"/>
<action selector="makeBaseWritingDirectionNatural:" destination="510" id="525"/>
<action selector="makeBaseWritingDirectionRightToLeft:" destination="512" id="527"/>
<action selector="makeTextWritingDirectionLeftToRight:" destination="516" id="529"/>
<action selector="makeTextWritingDirectionNatural:" destination="515" id="528"/>
<action selector="makeTextWritingDirectionRightToLeft:" destination="517" id="530"/>
<action selector="newDocument:" destination="82" id="373"/>
<action selector="openDocument:" destination="72" id="374"/>
<action selector="orderFrontColorPanel:" destination="401" id="433"/>
<action selector="orderFrontSubstitutionsPanel:" destination="457" id="458"/>
<action selector="paste:" destination="203" id="226"/>
<action selector="pasteAsPlainText:" destination="485" id="486"/>
<action selector="pasteFont:" destination="404" id="436"/>
<action selector="pasteRuler:" destination="507" id="519"/>
<action selector="performClose:" destination="73" id="193"/>
<action selector="performFindPanelAction:" destination="209" id="241"/>
<action selector="performFindPanelAction:" destination="208" id="487"/>
<action selector="performFindPanelAction:" destination="213" id="488"/>
<action selector="performFindPanelAction:" destination="221" id="489"/>
<action selector="performFindPanelAction:" destination="534" id="535"/>
<action selector="performMiniaturize:" destination="23" id="37"/>
<action selector="performZoom:" destination="239" id="240"/>
<action selector="print:" destination="78" id="86"/>
<action selector="raiseBaseline:" destination="409" id="426"/>
<action selector="redo:" destination="215" id="231"/>
<action selector="revertDocumentToSaved:" destination="112" id="364"/>
<action selector="runPageLayout:" destination="77" id="87"/>
<action selector="runToolbarCustomizationPalette:" destination="298" id="365"/>
<action selector="saveDocument:" destination="75" id="362"/>
<action selector="selectAll:" destination="198" id="232"/>
<action selector="showGuessPanel:" destination="204" id="230"/>
<action selector="showHelp:" destination="492" id="493"/>
<action selector="startSpeaking:" destination="196" id="233"/>
<action selector="stopSpeaking:" destination="195" id="227"/>
<action selector="subscript:" destination="408" id="429"/>
<action selector="superscript:" destination="407" id="430"/>
<action selector="tightenKerning:" destination="418" id="431"/>
<action selector="toggleAutomaticDashSubstitution:" destination="460" id="461"/>
<action selector="toggleAutomaticLinkDetection:" destination="354" id="357"/>
<action selector="toggleAutomaticQuoteSubstitution:" destination="351" id="356"/>
<action selector="toggleAutomaticSpellingCorrection:" destination="454" id="456"/>
<action selector="toggleAutomaticTextReplacement:" destination="462" id="463"/>
<action selector="toggleContinuousSpellChecking:" destination="219" id="222"/>
<action selector="toggleGrammarChecking:" destination="346" id="347"/>
<action selector="toggleRuler:" destination="505" id="520"/>
<action selector="toggleSmartInsertDelete:" destination="350" id="355"/>
<action selector="toggleToolbarShown:" destination="297" id="366"/>
<action selector="turnOffKerning:" destination="417" id="441"/>
<action selector="turnOffLigatures:" destination="413" id="440"/>
<action selector="underline:" destination="392" id="432"/>
<action selector="undo:" destination="207" id="223"/>
<action selector="unhideAllApplications:" destination="150" id="370"/>
<action selector="unscript:" destination="406" id="437"/>
<action selector="uppercaseWord:" destination="452" id="464"/>
<action selector="useAllLigatures:" destination="414" id="434"/>
<action selector="useStandardKerning:" destination="416" id="438"/>
<action selector="useStandardLigatures:" destination="412" id="439"/>
</connections>
</customObject>
<customObject id="-3" userLabel="Application">
<connections>
<action selector="terminate:" destination="136" id="449"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="EZAudioWaveformFromFileExample" id="56">
@@ -102,6 +19,9 @@
<items>
<menuItem title="About EZAudioWaveformFromFileExample" 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"/>
@@ -116,95 +36,211 @@
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide EZAudioWaveformFromFileExample" keyEquivalent="h" id="134"/>
<menuItem title="Hide EZAudioWaveformFromFileExample" 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 title="Show All" id="150"/>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit EZAudioWaveformFromFileExample" keyEquivalent="q" id="136"/>
<menuItem title="Quit EZAudioWaveformFromFileExample" 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"/>
<menuItem title="Open…" keyEquivalent="o" id="72"/>
<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"/>
<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"/>
<menuItem title="Save…" keyEquivalent="s" id="75"/>
<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>
<menuItem title="Print…" keyEquivalent="p" id="78"/>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="217">
<menu key="submenu" title="Edit" id="205">
<items>
<menuItem title="Undo" keyEquivalent="z" id="207"/>
<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"/>
<menuItem title="Copy" keyEquivalent="c" id="197"/>
<menuItem title="Paste" keyEquivalent="v" id="203"/>
<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 title="Delete" id="202"/>
<menuItem title="Select All" keyEquivalent="a" id="198"/>
<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"/>
<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 Next" tag="2" keyEquivalent="g" id="208"/>
<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>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
<menuItem title="Jump to Selection" keyEquivalent="j" id="210"/>
</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"/>
<menuItem title="Check Document Now" keyEquivalent=";" id="201"/>
<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"/>
<menuItem title="Check Grammar With Spelling" id="346"/>
<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>
@@ -214,18 +250,38 @@
<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"/>
<menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351"/>
<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>
@@ -236,12 +292,21 @@
<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>
@@ -249,8 +314,16 @@
<menuItem title="Speech" id="211">
<menu key="submenu" title="Speech" id="212">
<items>
<menuItem title="Start Speaking" id="196"/>
<menuItem title="Stop Speaking" id="195"/>
<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>
@@ -265,13 +338,37 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="388">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="389"/>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="390"/>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="391"/>
<menuItem title="Underline" keyEquivalent="u" id="392"/>
<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"/>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="395"/>
<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"/>
@@ -279,15 +376,27 @@
<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>
@@ -298,12 +407,21 @@
<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>
@@ -314,30 +432,55 @@
<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"/>
<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>
@@ -346,12 +489,27 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="497">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="498"/>
<menuItem title="Center" keyEquivalent="|" id="499"/>
<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 title="Align Right" keyEquivalent="}" id="501"/>
<menuItem isSeparatorItem="YES" id="502"/>
<menuItem title="Writing Direction" id="503">
<modifierMask key="keyEquivalentModifierMask"/>
@@ -363,14 +521,23 @@
<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">
@@ -379,14 +546,23 @@
<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>
@@ -394,12 +570,21 @@
<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>
@@ -412,20 +597,39 @@
<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>
<menuItem title="Customize Toolbar…" id="298"/>
</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"/>
<menuItem title="Zoom" id="239"/>
<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"/>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
@@ -433,17 +637,21 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="EZAudioWaveformFromFileExample Help" keyEquivalent="?" id="492"/>
<menuItem title="EZAudioWaveformFromFileExample Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="EZAudioWaveformFromFileExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="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="2560" height="1418"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
@@ -454,14 +662,6 @@
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager">
<connections>
<action selector="addFontTrait:" destination="390" id="421"/>
<action selector="addFontTrait:" destination="391" id="422"/>
<action selector="modifyFont:" destination="395" id="423"/>
<action selector="modifyFont:" destination="394" id="425"/>
<action selector="orderFrontFontPanel:" destination="389" id="424"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment version="1070" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="WaveformFromFileViewController">
@@ -19,53 +19,76 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="gA7-R7-vbt" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="0.0" width="480" height="211"/>
</customView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xHD-WQ-u4W">
<rect key="frame" x="14" y="224" width="125" height="32"/>
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<subviews>
<box autoresizesSubviews="NO" title="Box" boxType="custom" borderType="none" translatesAutoresizingMaskIntoConstraints="NO" id="dH6-TL-MVT">
<rect key="frame" x="0.0" y="193" width="480" height="79"/>
<view key="contentView">
<rect key="frame" x="0.0" y="0.0" width="480" height="79"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xHD-WQ-u4W">
<rect key="frame" x="10" y="11" width="125" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="113" id="b31-eU-mqu"/>
</constraints>
<buttonCell key="cell" type="push" title="Choose File..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7er-Dd-Gmx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="openFile:" target="-2" id="oIG-3z-prU"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="zS7-9z-YB1">
<rect key="frame" x="137" y="22" width="213" height="17"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" sendsActionOnEndEditing="YES" title="Label" id="jWL-Kx-s9B">
<font key="font" metaFont="system"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2Q5-5T-qQ4">
<rect key="frame" x="371" y="11" width="97" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="85" id="Xin-4w-yLk"/>
</constraints>
<buttonCell key="cell" type="push" title="Snapshot" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="8ht-Cu-65q">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="snapshot:" target="-2" id="RLS-Qr-Gbu"/>
</connections>
</button>
</subviews>
</view>
<constraints>
<constraint firstItem="zS7-9z-YB1" firstAttribute="leading" secondItem="xHD-WQ-u4W" secondAttribute="trailing" constant="10" id="7yh-7q-axR"/>
<constraint firstItem="2Q5-5T-qQ4" firstAttribute="leading" secondItem="zS7-9z-YB1" secondAttribute="trailing" constant="29" id="D3d-Ou-qaP"/>
<constraint firstAttribute="trailing" secondItem="2Q5-5T-qQ4" secondAttribute="trailing" constant="18" id="D9F-H4-mlu"/>
<constraint firstItem="zS7-9z-YB1" firstAttribute="top" secondItem="2Q5-5T-qQ4" secondAttribute="top" id="E0b-6r-tgF"/>
<constraint firstItem="xHD-WQ-u4W" firstAttribute="leading" secondItem="dH6-TL-MVT" secondAttribute="leading" constant="16" id="Ieb-er-Yqf"/>
<constraint firstItem="2Q5-5T-qQ4" firstAttribute="centerY" secondItem="dH6-TL-MVT" secondAttribute="centerY" constant="11" id="TG9-81-0jp"/>
<constraint firstItem="xHD-WQ-u4W" firstAttribute="top" secondItem="dH6-TL-MVT" secondAttribute="top" constant="40" id="aDV-Ry-Inv"/>
<constraint firstItem="2Q5-5T-qQ4" firstAttribute="baseline" secondItem="xHD-WQ-u4W" secondAttribute="baseline" id="yAV-WB-sKN"/>
</constraints>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" red="0.0" green="0.0" blue="0.0" alpha="0.69999999999999996" colorSpace="calibratedRGB"/>
</box>
</subviews>
<constraints>
<constraint firstAttribute="width" constant="113" id="0jv-eA-dSV"/>
<constraint firstAttribute="height" constant="21" id="1Yn-bF-mfb"/>
<constraint firstItem="dH6-TL-MVT" firstAttribute="leading" secondItem="gA7-R7-vbt" secondAttribute="leading" id="JWF-3n-y1m"/>
<constraint firstAttribute="trailing" secondItem="dH6-TL-MVT" secondAttribute="trailing" id="c6J-c1-evB"/>
<constraint firstItem="dH6-TL-MVT" firstAttribute="top" secondItem="gA7-R7-vbt" secondAttribute="top" id="yIc-KE-eyZ"/>
</constraints>
<buttonCell key="cell" type="push" title="Choose File..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7er-Dd-Gmx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="openFile:" target="-2" id="oIG-3z-prU"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zS7-9z-YB1">
<rect key="frame" x="141" y="235" width="213" height="17"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" sendsActionOnEndEditing="YES" title="Label" id="jWL-Kx-s9B">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Q5-5T-qQ4">
<rect key="frame" x="375" y="224" width="97" height="32"/>
<buttonCell key="cell" type="push" title="Snapshot" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="8ht-Cu-65q">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="snapshot:" target="-2" id="RLS-Qr-Gbu"/>
</connections>
</button>
</customView>
</subviews>
<constraints>
<constraint firstItem="zS7-9z-YB1" firstAttribute="leading" secondItem="xHD-WQ-u4W" secondAttribute="trailing" constant="10" id="4RW-fI-JJs"/>
<constraint firstItem="2Q5-5T-qQ4" firstAttribute="top" secondItem="0tP-1Y-eJu" secondAttribute="top" constant="20" id="E3b-p3-BoQ"/>
<constraint firstAttribute="trailing" relation="lessThanOrEqual" secondItem="zS7-9z-YB1" secondAttribute="trailing" constant="20" id="NTC-UB-Fma"/>
<constraint firstAttribute="trailing" secondItem="gA7-R7-vbt" secondAttribute="trailing" id="Tsg-V9-2HL"/>
<constraint firstItem="gA7-R7-vbt" firstAttribute="leading" secondItem="0tP-1Y-eJu" secondAttribute="leading" id="WAi-gw-Gx4"/>
<constraint firstItem="gA7-R7-vbt" firstAttribute="top" secondItem="xHD-WQ-u4W" secondAttribute="bottom" constant="20" id="fLd-J2-pdv"/>
<constraint firstItem="zS7-9z-YB1" firstAttribute="top" secondItem="0tP-1Y-eJu" secondAttribute="top" constant="20" id="gjc-Xh-3J0"/>
<constraint firstItem="xHD-WQ-u4W" firstAttribute="leading" secondItem="0tP-1Y-eJu" secondAttribute="leading" constant="20" id="ide-qF-Q25"/>
<constraint firstItem="xHD-WQ-u4W" firstAttribute="top" secondItem="0tP-1Y-eJu" secondAttribute="top" constant="20" id="iiM-ji-9ME"/>
<constraint firstAttribute="trailing" secondItem="2Q5-5T-qQ4" secondAttribute="trailing" constant="14" id="j3N-CF-2Rt"/>
<constraint firstAttribute="bottom" secondItem="gA7-R7-vbt" secondAttribute="bottom" id="nf1-Zn-U5V"/>
<constraint firstItem="gA7-R7-vbt" firstAttribute="leading" secondItem="0tP-1Y-eJu" secondAttribute="leading" id="1uQ-PM-GXF"/>
<constraint firstAttribute="trailing" secondItem="gA7-R7-vbt" secondAttribute="trailing" id="w4s-bY-9Vz"/>
<constraint firstItem="gA7-R7-vbt" firstAttribute="top" secondItem="0tP-1Y-eJu" secondAttribute="top" id="wko-ZW-xTr"/>
<constraint firstAttribute="bottom" secondItem="gA7-R7-vbt" secondAttribute="bottom" id="ynB-p6-1In"/>
</constraints>
</customView>
</objects>
@@ -24,6 +24,7 @@
667558B11B3B604B0013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 6675589C1B3B604B0013E67E /* TPCircularBuffer.c */; };
667558B21B3B604B0013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 6675589F1B3B604B0013E67E /* CHANGELOG */; };
667558B31B3B604B0013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 667558A01B3B604B0013E67E /* VERSION */; };
667EEA451B51EF4E00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA441B51EF4E00D57FB2 /* EZAudioFFT.m */; };
66DB85831B0430E70018EFC5 /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 66DB85821B0430E70018EFC5 /* MainStoryboard.storyboard */; };
94056F7E185E593500EB94BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056F7D185E593500EB94BA /* Foundation.framework */; };
94056F80185E593500EB94BA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056F7F185E593500EB94BA /* CoreGraphics.framework */; };
@@ -86,6 +87,8 @@
6675589D1B3B604B0013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
6675589F1B3B604B0013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
667558A01B3B604B0013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA431B51EF4E00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA441B51EF4E00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
66DB85821B0430E70018EFC5 /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = "<group>"; };
94056F7A185E593500EB94BA /* EZAudioCoreGraphicsWaveformExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioCoreGraphicsWaveformExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
94056F7D185E593500EB94BA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -146,6 +149,8 @@
667558811B3B604B0013E67E /* EZAudioDevice.m */,
667558821B3B604B0013E67E /* EZAudioDisplayLink.h */,
667558831B3B604B0013E67E /* EZAudioDisplayLink.m */,
667EEA431B51EF4E00D57FB2 /* EZAudioFFT.h */,
667EEA441B51EF4E00D57FB2 /* EZAudioFFT.m */,
667558841B3B604B0013E67E /* EZAudioFile.h */,
667558851B3B604B0013E67E /* EZAudioFile.m */,
667558861B3B604B0013E67E /* EZAudioFloatConverter.h */,
@@ -365,6 +370,7 @@
667558A81B3B604B0013E67E /* EZAudioPlayer.m in Sources */,
94056FDE185E59D900EB94BA /* CoreGraphicsWaveformViewController.m in Sources */,
667558AA1B3B604B0013E67E /* EZAudioPlotGL.m in Sources */,
667EEA451B51EF4E00D57FB2 /* EZAudioFFT.m in Sources */,
667558A51B3B604B0013E67E /* EZAudioFile.m in Sources */,
667558AE1B3B604B0013E67E /* EZOutput.m in Sources */,
667558AC1B3B604B0013E67E /* EZAudioUtilities.m in Sources */,
@@ -24,7 +24,7 @@
}
//------------------------------------------------------------------------------
#pragma mark - Customize the Audio Plot
#pragma mark - Setup
//------------------------------------------------------------------------------
- (void)viewDidLoad
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="uAJ-Uz-eFq">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="uAJ-Uz-eFq">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
@@ -25,6 +25,7 @@
667559231B3B78720013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 6675590E1B3B78720013E67E /* TPCircularBuffer.c */; };
667559241B3B78720013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 667559111B3B78720013E67E /* CHANGELOG */; };
667559251B3B78720013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 667559121B3B78720013E67E /* VERSION */; };
667EEA511B51EF7F00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA501B51EF7F00D57FB2 /* EZAudioFFT.m */; };
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 */; };
@@ -88,6 +89,8 @@
6675590F1B3B78720013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
667559111B3B78720013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
667559121B3B78720013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA4F1B51EF7F00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA501B51EF7F00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
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; };
@@ -149,6 +152,8 @@
667558F31B3B78720013E67E /* EZAudioDevice.m */,
667558F41B3B78720013E67E /* EZAudioDisplayLink.h */,
667558F51B3B78720013E67E /* EZAudioDisplayLink.m */,
667EEA4F1B51EF7F00D57FB2 /* EZAudioFFT.h */,
667EEA501B51EF7F00D57FB2 /* EZAudioFFT.m */,
667558F61B3B78720013E67E /* EZAudioFile.h */,
667558F71B3B78720013E67E /* EZAudioFile.m */,
667558F81B3B78720013E67E /* EZAudioFloatConverter.h */,
@@ -369,6 +374,7 @@
6675591A1B3B78720013E67E /* EZAudioPlayer.m in Sources */,
9417A97C1871E88300D9D37B /* AppDelegate.m in Sources */,
6675591C1B3B78720013E67E /* EZAudioPlotGL.m in Sources */,
667EEA511B51EF7F00D57FB2 /* EZAudioFFT.m in Sources */,
667559171B3B78720013E67E /* EZAudioFile.m in Sources */,
667559201B3B78720013E67E /* EZOutput.m in Sources */,
6675591E1B3B78720013E67E /* EZAudioUtilities.m in Sources */,
@@ -506,6 +512,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExample/EZAudioFFTExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -519,6 +526,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioFFTExample/EZAudioFFTExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioFFTExample/EZAudioFFTExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -30,15 +30,10 @@
*/
#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>
@interface FFTViewController : UIViewController <EZMicrophoneDelegate, EZAudioFFTDelegate>
//------------------------------------------------------------------------------
#pragma mark - Components
@@ -55,8 +50,18 @@
@property (nonatomic,weak) IBOutlet EZAudioPlot *audioPlotTime;
/**
Microphone
A label used to display the maximum frequency (i.e. the frequency with the highest energy) calculated from the FFT.
*/
@property (nonatomic, weak) IBOutlet UILabel *maxFrequencyLabel;
/**
The microphone used to get input.
*/
@property (nonatomic,strong) EZMicrophone *microphone;
/**
Used to calculate a rolling FFT of the incoming audio data.
*/
@property (nonatomic, strong) EZAudioFFTRolling *fft;
@end
@@ -25,156 +25,98 @@
#import "FFTViewController.h"
@interface FFTViewController (){
COMPLEX_SPLIT _A;
FFTSetup _FFTSetup;
BOOL _isFFTSetup;
vDSP_Length _log2n;
}
@end
static vDSP_Length const FFTViewControllerFFTWindowSize = 4096;
@implementation FFTViewController
@synthesize audioPlotFreq;
@synthesize audioPlotTime;
@synthesize microphone;
//------------------------------------------------------------------------------
#pragma mark - Status Bar Style
//------------------------------------------------------------------------------
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
#pragma mark - Customize the Audio Plot
//------------------------------------------------------------------------------
#pragma mark - View Lifecycle
//------------------------------------------------------------------------------
- (void)viewDidLoad
{
[super viewDidLoad];
//
// Setup the AVAudioSession. EZMicrophone will not work properly on iOS
// if you don't do this!
//
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
if (error)
{
NSLog(@"Error setting up audio session category: %@", error.localizedDescription);
}
[session setActive:YES error:&error];
if (error)
{
NSLog(@"Error setting up audio session active: %@", error.localizedDescription);
}
/*
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;
//
self.audioPlotTime.plotType = EZPlotTypeBuffer;
self.maxFrequencyLabel.numberOfLines = 0;
//
// 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;
//
self.audioPlotFreq.shouldFill = YES;
self.audioPlotFreq.plotType = EZPlotTypeBuffer;
self.audioPlotFreq.shouldCenterYAxis = NO;
/*
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] = [EZAudioUtilities MAP:mag leftMin:0.0 leftMax:maxMag rightMin:0.0 rightMax:1.0];
}
// Update the frequency domain plot
[self.audioPlotFreq updateBuffer:amp
withBufferSize:nOver2];
//
// Create an instance of the microphone and tell it to use this view controller instance as the delegate
//
self.microphone = [EZMicrophone microphoneWithDelegate:self];
//
// Create an instance of the EZAudioFFTRolling to keep a history of the incoming audio data and calculate the FFT.
//
self.fft = [EZAudioFFTRolling fftWithWindowSize:FFTViewControllerFFTWindowSize
sampleRate:self.microphone.audioStreamBasicDescription.mSampleRate
delegate:self];
//
// Start the mic
//
[self.microphone startFetchingAudio];
}
//------------------------------------------------------------------------------
#pragma mark - EZMicrophoneDelegate
//------------------------------------------------------------------------------
-(void) microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels {
dispatch_async(dispatch_get_main_queue(), ^{
withNumberOfChannels:(UInt32)numberOfChannels
{
//
// Calculate the FFT, will trigger EZAudioFFTDelegate
//
[self.fft computeFFTWithBuffer:buffer[0] withBufferSize:bufferSize];
// 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]];
});
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.audioPlotTime updateBuffer:buffer[0]
withBufferSize:bufferSize];
});
}
//------------------------------------------------------------------------------
#pragma mark - EZAudioFFTDelegate
//------------------------------------------------------------------------------
- (void) fft:(EZAudioFFT *)fft
updatedWithFFTData:(float *)fftData
bufferSize:(vDSP_Length)bufferSize
{
float maxFrequency = [fft maxFrequency];
NSString *noteName = [EZAudioUtilities noteNameStringForFrequency:maxFrequency
includeOctave:YES];
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.maxFrequencyLabel.text = [NSString stringWithFormat:@"Highest Note: %@,\nFrequency: %.2f", noteName, maxFrequency];
[weakSelf.audioPlotFreq updateBuffer:fftData withBufferSize:(UInt32)bufferSize];
});
}
//------------------------------------------------------------------------------
@end
@@ -13,39 +13,53 @@
<viewControllerLayoutGuide type="top" id="Gb6-mY-qlI"/>
<viewControllerLayoutGuide type="bottom" id="YgU-XB-3Wp"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="qdz-w1-Fnd">
<view key="view" contentMode="scaleToFill" id="qdz-w1-Fnd" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rTC-r5-1nY" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="300" width="600" height="300"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OQU-xT-TSP" customClass="EZAudioPlot">
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2rO-IY-dvl" customClass="EZAudioPlot">
<rect key="frame" x="18" y="18" width="564" height="64"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="64" id="V1K-Jj-DhO"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
<color key="value" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="color">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jcb-nb-Ibd">
<rect key="frame" x="18" y="100" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="rTC-r5-1nY" firstAttribute="top" secondItem="OQU-xT-TSP" secondAttribute="bottom" id="Gvx-p5-QUo"/>
<constraint firstAttribute="trailing" secondItem="OQU-xT-TSP" secondAttribute="trailing" id="Jas-mw-vJx"/>
<constraint firstItem="rTC-r5-1nY" firstAttribute="leading" secondItem="qdz-w1-Fnd" secondAttribute="leading" id="L4g-Ae-9tj"/>
<constraint firstItem="rTC-r5-1nY" firstAttribute="leading" secondItem="qdz-w1-Fnd" secondAttribute="leading" id="R76-NA-7Bd"/>
<constraint firstAttribute="trailing" secondItem="rTC-r5-1nY" secondAttribute="trailing" id="SD1-rQ-K9f"/>
<constraint firstItem="OQU-xT-TSP" firstAttribute="leading" secondItem="qdz-w1-Fnd" secondAttribute="leading" id="Ylv-YL-VNN"/>
<constraint firstItem="rTC-r5-1nY" firstAttribute="height" secondItem="OQU-xT-TSP" secondAttribute="height" id="c8v-Wf-j6b"/>
<constraint firstItem="OQU-xT-TSP" firstAttribute="leading" secondItem="qdz-w1-Fnd" secondAttribute="leading" id="cky-9G-OUa"/>
<constraint firstItem="YgU-XB-3Wp" firstAttribute="top" secondItem="rTC-r5-1nY" secondAttribute="bottom" id="diI-fy-02O"/>
<constraint firstAttribute="trailing" secondItem="OQU-xT-TSP" secondAttribute="trailing" id="eU7-t0-VFY"/>
<constraint firstItem="OQU-xT-TSP" firstAttribute="top" secondItem="qdz-w1-Fnd" secondAttribute="top" id="vV1-yG-7ff"/>
<constraint firstAttribute="trailing" secondItem="rTC-r5-1nY" secondAttribute="trailing" id="whu-w2-7Ne"/>
<constraint firstItem="OQU-xT-TSP" firstAttribute="top" secondItem="qdz-w1-Fnd" secondAttribute="top" id="zIe-GV-q0c"/>
<constraint firstItem="2rO-IY-dvl" firstAttribute="leading" secondItem="qdz-w1-Fnd" secondAttribute="leading" constant="18" id="8Ww-vp-FX4"/>
<constraint firstAttribute="trailing" secondItem="2rO-IY-dvl" secondAttribute="trailing" constant="18" id="AJT-fs-rh8"/>
<constraint firstItem="Jcb-nb-Ibd" firstAttribute="top" secondItem="2rO-IY-dvl" secondAttribute="bottom" constant="18" id="LrN-Wx-JIp"/>
<constraint firstItem="Jcb-nb-Ibd" firstAttribute="leading" secondItem="2rO-IY-dvl" secondAttribute="leading" id="QHW-YQ-Jh0"/>
<constraint firstItem="2rO-IY-dvl" firstAttribute="top" secondItem="qdz-w1-Fnd" secondAttribute="top" constant="18" id="Thl-Cl-cSH"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="backgroundColor">
<color key="value" red="0.0078431372550000003" green="0.72156862749999995" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="color">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<connections>
<outlet property="audioPlotFreq" destination="rTC-r5-1nY" id="CRN-vl-avP"/>
<outlet property="audioPlotTime" destination="OQU-xT-TSP" id="zfe-04-ywd"/>
<outlet property="audioPlotFreq" destination="qdz-w1-Fnd" id="TKq-sR-dWl"/>
<outlet property="audioPlotTime" destination="2rO-IY-dvl" id="14G-ei-FpB"/>
<outlet property="maxFrequencyLabel" destination="Jcb-nb-Ibd" id="F5A-UP-Fik"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="xe6-rr-s1W" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -24,6 +24,7 @@
66755A071B3B78940013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 667559F21B3B78940013E67E /* TPCircularBuffer.c */; };
66755A081B3B78940013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 667559F51B3B78940013E67E /* CHANGELOG */; };
66755A091B3B78940013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 667559F61B3B78940013E67E /* VERSION */; };
667EEA421B51EF4200D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA411B51EF4200D57FB2 /* EZAudioFFT.m */; };
66DB85B81B05714F0018EFC5 /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 66DB85B71B05714F0018EFC5 /* MainStoryboard.storyboard */; };
94056FEC185E5EAF00EB94BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056FEB185E5EAF00EB94BA /* Foundation.framework */; };
94056FEE185E5EAF00EB94BA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94056FED185E5EAF00EB94BA /* CoreGraphics.framework */; };
@@ -86,6 +87,8 @@
667559F31B3B78940013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
667559F51B3B78940013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
667559F61B3B78940013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA401B51EF4200D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA411B51EF4200D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
66DB85B71B05714F0018EFC5 /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = "<group>"; };
94056FE8185E5EAF00EB94BA /* EZAudioOpenGLWaveformExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioOpenGLWaveformExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
94056FEB185E5EAF00EB94BA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -146,6 +149,8 @@
667559D71B3B78940013E67E /* EZAudioDevice.m */,
667559D81B3B78940013E67E /* EZAudioDisplayLink.h */,
667559D91B3B78940013E67E /* EZAudioDisplayLink.m */,
667EEA401B51EF4200D57FB2 /* EZAudioFFT.h */,
667EEA411B51EF4200D57FB2 /* EZAudioFFT.m */,
667559DA1B3B78940013E67E /* EZAudioFile.h */,
667559DB1B3B78940013E67E /* EZAudioFile.m */,
667559DC1B3B78940013E67E /* EZAudioFloatConverter.h */,
@@ -365,6 +370,7 @@
667559FE1B3B78940013E67E /* EZAudioPlayer.m in Sources */,
94057050185E636100EB94BA /* OpenGLWaveformViewController.m in Sources */,
66755A001B3B78940013E67E /* EZAudioPlotGL.m in Sources */,
667EEA421B51EF4200D57FB2 /* EZAudioFFT.m in Sources */,
667559FB1B3B78940013E67E /* EZAudioFile.m in Sources */,
66755A041B3B78940013E67E /* EZOutput.m in Sources */,
66755A021B3B78940013E67E /* EZAudioUtilities.m in Sources */,
@@ -502,6 +508,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -515,6 +522,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioOpenGLWaveformExample/EZAudioOpenGLWaveformExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="1v1-63-VYU">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
@@ -24,7 +24,7 @@
}
//------------------------------------------------------------------------------
#pragma mark - Customize the Audio Plot
#pragma mark - Setup
//------------------------------------------------------------------------------
- (void)viewDidLoad
@@ -25,6 +25,7 @@
6675595C1B3B78790013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 667559471B3B78790013E67E /* TPCircularBuffer.c */; };
6675595D1B3B78790013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 6675594A1B3B78790013E67E /* CHANGELOG */; };
6675595E1B3B78790013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 6675594B1B3B78790013E67E /* VERSION */; };
667EEA4E1B51EF7200D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA4D1B51EF7200D57FB2 /* EZAudioFFT.m */; };
9417A60E1864D4DC00D9D37B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A60D1864D4DC00D9D37B /* Foundation.framework */; };
9417A6101864D4DC00D9D37B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A60F1864D4DC00D9D37B /* CoreGraphics.framework */; };
9417A6121864D4DC00D9D37B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A6111864D4DC00D9D37B /* UIKit.framework */; };
@@ -87,6 +88,8 @@
667559481B3B78790013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
6675594A1B3B78790013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
6675594B1B3B78790013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA4C1B51EF7200D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA4D1B51EF7200D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
9417A60A1864D4DC00D9D37B /* EZAudioPassThroughExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioPassThroughExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
9417A60D1864D4DC00D9D37B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
9417A60F1864D4DC00D9D37B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@@ -146,6 +149,8 @@
6675592C1B3B78790013E67E /* EZAudioDevice.m */,
6675592D1B3B78790013E67E /* EZAudioDisplayLink.h */,
6675592E1B3B78790013E67E /* EZAudioDisplayLink.m */,
667EEA4C1B51EF7200D57FB2 /* EZAudioFFT.h */,
667EEA4D1B51EF7200D57FB2 /* EZAudioFFT.m */,
6675592F1B3B78790013E67E /* EZAudioFile.h */,
667559301B3B78790013E67E /* EZAudioFile.m */,
667559311B3B78790013E67E /* EZAudioFloatConverter.h */,
@@ -365,6 +370,7 @@
667559531B3B78790013E67E /* EZAudioPlayer.m in Sources */,
9417A61E1864D4DC00D9D37B /* AppDelegate.m in Sources */,
667559551B3B78790013E67E /* EZAudioPlotGL.m in Sources */,
667EEA4E1B51EF7200D57FB2 /* EZAudioFFT.m in Sources */,
667559501B3B78790013E67E /* EZAudioFile.m in Sources */,
667559591B3B78790013E67E /* EZOutput.m in Sources */,
667559571B3B78790013E67E /* EZAudioUtilities.m in Sources */,
@@ -502,6 +508,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioPassThroughExample/EZAudioPassThroughExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioPassThroughExample/EZAudioPassThroughExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -515,6 +522,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioPassThroughExample/EZAudioPassThroughExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioPassThroughExample/EZAudioPassThroughExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="zGs-8g-w7u">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="zGs-8g-w7u">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<scenes>
<!--Pass Through View Controller-->
@@ -25,6 +25,7 @@
667558EA1B3B60B80013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 667558D51B3B60B80013E67E /* TPCircularBuffer.c */; };
667558EB1B3B60B80013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 667558D81B3B60B80013E67E /* CHANGELOG */; };
667558EC1B3B60B80013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 667558D91B3B60B80013E67E /* VERSION */; };
667EEA3F1B51EF2D00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA3E1B51EF2D00D57FB2 /* EZAudioFFT.m */; };
9417A6C718658FB500D9D37B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A6C618658FB500D9D37B /* AudioToolbox.framework */; };
9417A6C918658FC000D9D37B /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A6C818658FC000D9D37B /* GLKit.framework */; };
9417A6D1186591CA00D9D37B /* simple-drum-beat.wav in Resources */ = {isa = PBXBuildFile; fileRef = 9417A6D0186591CA00D9D37B /* simple-drum-beat.wav */; };
@@ -88,6 +89,8 @@
667558D61B3B60B80013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
667558D81B3B60B80013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
667558D91B3B60B80013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA3D1B51EF2D00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA3E1B51EF2D00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
9417A6C618658FB500D9D37B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
9417A6C818658FC000D9D37B /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
9417A6D0186591CA00D9D37B /* simple-drum-beat.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = "simple-drum-beat.wav"; path = "../../../simple-drum-beat.wav"; sourceTree = "<group>"; };
@@ -148,6 +151,8 @@
667558BA1B3B60B80013E67E /* EZAudioDevice.m */,
667558BB1B3B60B80013E67E /* EZAudioDisplayLink.h */,
667558BC1B3B60B80013E67E /* EZAudioDisplayLink.m */,
667EEA3D1B51EF2D00D57FB2 /* EZAudioFFT.h */,
667EEA3E1B51EF2D00D57FB2 /* EZAudioFFT.m */,
667558BD1B3B60B80013E67E /* EZAudioFile.h */,
667558BE1B3B60B80013E67E /* EZAudioFile.m */,
667558BF1B3B60B80013E67E /* EZAudioFloatConverter.h */,
@@ -369,6 +374,7 @@
667558E11B3B60B80013E67E /* EZAudioPlayer.m in Sources */,
944D03ED186038A60076EF7A /* AppDelegate.m in Sources */,
667558E31B3B60B80013E67E /* EZAudioPlotGL.m in Sources */,
667EEA3F1B51EF2D00D57FB2 /* EZAudioFFT.m in Sources */,
667558DE1B3B60B80013E67E /* EZAudioFile.m in Sources */,
667558E71B3B60B80013E67E /* EZOutput.m in Sources */,
667558E51B3B60B80013E67E /* EZAudioUtilities.m in Sources */,
@@ -506,6 +512,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioPlayFileExample/EZAudioPlayFileExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioPlayFileExample/EZAudioPlayFileExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -519,6 +526,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioPlayFileExample/EZAudioPlayFileExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioPlayFileExample/EZAudioPlayFileExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="scx-fQ-Cxi">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<scenes>
@@ -29,7 +29,7 @@
}
//------------------------------------------------------------------------------
#pragma mark - Customize the Audio Plot
#pragma mark - Setup
//------------------------------------------------------------------------------
- (void)viewDidLoad
@@ -42,7 +42,7 @@
//
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
[session setCategory:AVAudioSessionCategoryPlayback error:&error];
if (error)
{
NSLog(@"Error setting up audio session category: %@", error.localizedDescription);
@@ -62,6 +62,8 @@
self.audioPlot.shouldFill = YES;
self.audioPlot.shouldMirror = YES;
NSLog(@"outputs: %@", [EZAudioDevice outputDevices]);
//
// Create the audio player
//
@@ -197,7 +199,8 @@
[self.audioFile getWaveformDataWithCompletionBlock:^(float **waveformData,
int length)
{
[weakSelf.audioPlot updateBuffer:waveformData[0] withBufferSize:length];
[weakSelf.audioPlot updateBuffer:waveformData[0]
withBufferSize:length];
}];
//
@@ -216,6 +219,11 @@
}
else
{
if (self.audioPlot.shouldMirror && (self.audioPlot.plotType == EZPlotTypeBuffer))
{
self.audioPlot.shouldMirror = NO;
self.audioPlot.shouldFill = NO;
}
[self.player play];
}
}
@@ -25,6 +25,7 @@
667559CE1B3B78890013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 667559B91B3B78890013E67E /* TPCircularBuffer.c */; };
667559CF1B3B78890013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 667559BC1B3B78890013E67E /* CHANGELOG */; };
667559D01B3B78890013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 667559BD1B3B78890013E67E /* VERSION */; };
667EEA481B51EF5C00D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA471B51EF5C00D57FB2 /* EZAudioFFT.m */; };
940570CC185E7F8300EB94BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 940570CB185E7F8300EB94BA /* Foundation.framework */; };
940570CE185E7F8300EB94BA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 940570CD185E7F8300EB94BA /* CoreGraphics.framework */; };
940570D0185E7F8300EB94BA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 940570CF185E7F8300EB94BA /* UIKit.framework */; };
@@ -87,6 +88,8 @@
667559BA1B3B78890013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
667559BC1B3B78890013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
667559BD1B3B78890013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA461B51EF5C00D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA471B51EF5C00D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
940570C8185E7F8300EB94BA /* EZAudioRecordExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioRecordExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
940570CB185E7F8300EB94BA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
940570CD185E7F8300EB94BA /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@@ -146,6 +149,8 @@
6675599E1B3B78890013E67E /* EZAudioDevice.m */,
6675599F1B3B78890013E67E /* EZAudioDisplayLink.h */,
667559A01B3B78890013E67E /* EZAudioDisplayLink.m */,
667EEA461B51EF5C00D57FB2 /* EZAudioFFT.h */,
667EEA471B51EF5C00D57FB2 /* EZAudioFFT.m */,
667559A11B3B78890013E67E /* EZAudioFile.h */,
667559A21B3B78890013E67E /* EZAudioFile.m */,
667559A31B3B78890013E67E /* EZAudioFloatConverter.h */,
@@ -365,6 +370,7 @@
667559C51B3B78890013E67E /* EZAudioPlayer.m in Sources */,
94057105185E805900EB94BA /* RecordViewController.m in Sources */,
667559C71B3B78890013E67E /* EZAudioPlotGL.m in Sources */,
667EEA481B51EF5C00D57FB2 /* EZAudioFFT.m in Sources */,
667559C21B3B78890013E67E /* EZAudioFile.m in Sources */,
667559CB1B3B78890013E67E /* EZOutput.m in Sources */,
667559C91B3B78890013E67E /* EZAudioUtilities.m in Sources */,
@@ -502,6 +508,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioRecordExample/EZAudioRecordExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioRecordExample/EZAudioRecordExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -515,6 +522,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioRecordExample/EZAudioRecordExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioRecordExample/EZAudioRecordExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="llE-BN-jHz">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="llE-BN-jHz">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<scenes>
<!--Record View Controller-->
@@ -20,70 +20,91 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2wj-z5-SgU" customClass="EZAudioPlotGL">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1hg-FO-pPe">
<rect key="frame" x="18" y="512" width="51" height="31"/>
<color key="onTintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<action selector="toggleMicrophone:" destination="llE-BN-jHz" eventType="valueChanged" id="gDV-6T-Whu"/>
</connections>
</switch>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Microphone On" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0aj-Ap-Ylp">
<rect key="frame" x="85" y="520" width="497" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="x5e-xg-u5V">
<rect key="frame" x="18" y="551" width="51" height="31"/>
<connections>
<action selector="toggleRecording:" destination="llE-BN-jHz" eventType="valueChanged" id="XcR-8d-Kcd"/>
</connections>
</switch>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Recording On" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e1t-nE-3QJ">
<rect key="frame" x="85" y="559" width="497" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="r8j-qU-fh6">
<rect key="frame" x="18" y="474" width="49" height="30"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ua2-c0-har">
<rect key="frame" x="0.0" y="455" width="600" height="145"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1hg-FO-pPe">
<rect key="frame" x="18" y="57" width="51" height="31"/>
<color key="onTintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<action selector="toggleMicrophone:" destination="llE-BN-jHz" eventType="valueChanged" id="gDV-6T-Whu"/>
</connections>
</switch>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Microphone On" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0aj-Ap-Ylp">
<rect key="frame" x="85" y="65" width="497" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="x5e-xg-u5V">
<rect key="frame" x="18" y="96" width="51" height="31"/>
<color key="onTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<connections>
<action selector="toggleRecording:" destination="llE-BN-jHz" eventType="valueChanged" id="XcR-8d-Kcd"/>
</connections>
</switch>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Recording On" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e1t-nE-3QJ">
<rect key="frame" x="85" y="104" width="497" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Not Playing" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zeh-I6-Na6">
<rect key="frame" x="85" y="26" width="497" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lex-aP-CGX">
<rect key="frame" x="13" y="19" width="59" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="LDk-Y3-uk0"/>
<constraint firstAttribute="width" constant="59" id="zqS-lz-oEK"/>
</constraints>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="13"/>
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<state key="normal" title="Play">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="playFile:" destination="llE-BN-jHz" eventType="touchUpInside" id="DDY-Cz-2IW"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.70000000000000007" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="dbU-fb-Yp6"/>
<constraint firstAttribute="width" constant="49" id="jPi-0p-2oF"/>
<constraint firstAttribute="height" constant="145" id="84N-gU-Dz9"/>
<constraint firstAttribute="trailing" secondItem="zeh-I6-Na6" secondAttribute="trailing" constant="18" id="Nnf-8H-wts"/>
<constraint firstItem="Lex-aP-CGX" firstAttribute="leading" secondItem="Ua2-c0-har" secondAttribute="leading" constant="13" id="Zb4-yY-8dM"/>
<constraint firstItem="zeh-I6-Na6" firstAttribute="top" secondItem="Ua2-c0-har" secondAttribute="top" constant="26" id="l3q-uD-w0G"/>
<constraint firstItem="zeh-I6-Na6" firstAttribute="leading" secondItem="Lex-aP-CGX" secondAttribute="trailing" constant="13" id="mnu-nJ-xAa"/>
<constraint firstItem="Lex-aP-CGX" firstAttribute="top" secondItem="Ua2-c0-har" secondAttribute="top" constant="19" id="tAe-da-Jb2"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<state key="normal" title="Play">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="playFile:" destination="llE-BN-jHz" eventType="touchUpInside" id="IbI-bz-M5D"/>
</connections>
</button>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Not Playing" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zeh-I6-Na6">
<rect key="frame" x="85" y="481" width="497" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QZk-8t-iz0">
<rect key="frame" x="18" y="18" width="80" height="39"/>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="32"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NK6-i1-Kjf" customClass="EZAudioPlot">
<rect key="frame" x="107" y="18" width="475" height="39"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="39" id="pnN-yp-8eE"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="0aj-Ap-Ylp" firstAttribute="centerY" secondItem="1hg-FO-pPe" secondAttribute="centerY" id="2ID-SH-h0n"/>
<constraint firstItem="x5e-xg-u5V" firstAttribute="centerY" secondItem="e1t-nE-3QJ" secondAttribute="centerY" id="3TN-JD-fXs"/>
<constraint firstAttribute="trailing" secondItem="0aj-Ap-Ylp" secondAttribute="trailing" constant="18" id="Nzq-x0-Bn3"/>
<constraint firstItem="1hg-FO-pPe" firstAttribute="leading" secondItem="2wj-z5-SgU" secondAttribute="leading" constant="18" id="SGf-Ot-ydT"/>
<constraint firstItem="zeh-I6-Na6" firstAttribute="centerY" secondItem="r8j-qU-fh6" secondAttribute="centerY" id="SV5-g6-nAm"/>
<constraint firstItem="zeh-I6-Na6" firstAttribute="leading" secondItem="r8j-qU-fh6" secondAttribute="trailing" constant="18" id="WrE-fc-eWU"/>
<constraint firstItem="0aj-Ap-Ylp" firstAttribute="leading" secondItem="1hg-FO-pPe" secondAttribute="trailing" constant="18" id="Zlu-hy-toc"/>
<constraint firstItem="r8j-qU-fh6" firstAttribute="leading" secondItem="2wj-z5-SgU" secondAttribute="leading" constant="18" id="bfv-fU-4be"/>
<constraint firstItem="e1t-nE-3QJ" firstAttribute="leading" secondItem="x5e-xg-u5V" secondAttribute="trailing" constant="18" id="cyW-VV-2vF"/>
<constraint firstItem="x5e-xg-u5V" firstAttribute="leading" secondItem="2wj-z5-SgU" secondAttribute="leading" constant="18" id="d1D-pw-daz"/>
<constraint firstAttribute="bottom" secondItem="x5e-xg-u5V" secondAttribute="bottom" constant="18" id="j5C-Pr-Qr1"/>
<constraint firstItem="1hg-FO-pPe" firstAttribute="top" secondItem="r8j-qU-fh6" secondAttribute="bottom" constant="8" id="kGE-En-5oO"/>
<constraint firstAttribute="trailing" secondItem="zeh-I6-Na6" secondAttribute="trailing" constant="18" id="lgq-o9-XKk"/>
<constraint firstAttribute="trailing" secondItem="e1t-nE-3QJ" secondAttribute="trailing" constant="18" id="yg8-Wi-4FL"/>
<constraint firstItem="x5e-xg-u5V" firstAttribute="top" secondItem="1hg-FO-pPe" secondAttribute="bottom" constant="8" id="zO4-XU-4yd"/>
<constraint firstItem="QZk-8t-iz0" firstAttribute="top" secondItem="2wj-z5-SgU" secondAttribute="top" constant="18" id="7aU-qh-lzs"/>
<constraint firstItem="QZk-8t-iz0" firstAttribute="leading" secondItem="2wj-z5-SgU" secondAttribute="leading" constant="18" id="Aac-ba-fJG"/>
<constraint firstAttribute="trailing" secondItem="NK6-i1-Kjf" secondAttribute="trailing" constant="18" id="BAg-ql-P64"/>
<constraint firstAttribute="trailing" secondItem="Ua2-c0-har" secondAttribute="trailing" id="DFS-Lr-ap6"/>
<constraint firstAttribute="bottom" secondItem="Ua2-c0-har" secondAttribute="bottom" id="hWL-2I-U11"/>
<constraint firstItem="Ua2-c0-har" firstAttribute="leading" secondItem="2wj-z5-SgU" secondAttribute="leading" id="jV7-AG-ClO"/>
<constraint firstItem="NK6-i1-Kjf" firstAttribute="leading" secondItem="QZk-8t-iz0" secondAttribute="trailing" constant="9" id="rqh-Ib-RFU"/>
<constraint firstItem="NK6-i1-Kjf" firstAttribute="top" secondItem="2wj-z5-SgU" secondAttribute="top" constant="18" id="tRd-Ee-lnl"/>
</constraints>
</view>
</subviews>
@@ -96,13 +117,15 @@
</constraints>
</view>
<connections>
<outlet property="audioPlot" destination="2wj-z5-SgU" id="1ih-MQ-w9g"/>
<outlet property="currentTimeLabel" destination="QZk-8t-iz0" id="MP6-0t-jhv"/>
<outlet property="microphoneStateLabel" destination="0aj-Ap-Ylp" id="fb1-B6-aY6"/>
<outlet property="microphoneSwitch" destination="1hg-FO-pPe" id="SFI-AX-IjC"/>
<outlet property="microphoneTextField" destination="0aj-Ap-Ylp" id="748-Fq-ubg"/>
<outlet property="playButton" destination="r8j-qU-fh6" id="tmR-Nt-pKO"/>
<outlet property="playingTextField" destination="zeh-I6-Na6" id="bsZ-bd-HDD"/>
<outlet property="playButton" destination="Lex-aP-CGX" id="K8T-X8-Tfy"/>
<outlet property="playingAudioPlot" destination="NK6-i1-Kjf" id="bes-5F-Cfa"/>
<outlet property="playingStateLabel" destination="zeh-I6-Na6" id="Tpj-mT-wwx"/>
<outlet property="recordSwitch" destination="x5e-xg-u5V" id="yZ8-zX-x4o"/>
<outlet property="recordingTextField" destination="e1t-nE-3QJ" id="Vr4-cl-5zt"/>
<outlet property="recordingAudioPlot" destination="2wj-z5-SgU" id="2hH-vO-WSb"/>
<outlet property="recordingStateLabel" destination="e1t-nE-3QJ" id="PDc-R4-k0n"/>
<outlet property="view" destination="PCx-Sz-N5f" id="fk5-lV-jnA"/>
</connections>
</viewController>
@@ -11,48 +11,127 @@
// Import EZAudio header
#import "EZAudio.h"
// Import AVFoundation to play the file (will save EZAudioFile and EZOutput for separate example)
#import <AVFoundation/AVFoundation.h>
// By default this will record a file to the application's documents directory (within the application's sandbox)
#define kAudioFilePath @"EZAudioTest.m4a"
@interface RecordViewController : UIViewController <AVAudioPlayerDelegate,EZMicrophoneDelegate>
//------------------------------------------------------------------------------
#pragma mark - RecordViewController
//------------------------------------------------------------------------------
@interface RecordViewController : UIViewController <EZAudioPlayerDelegate,
EZMicrophoneDelegate,
EZRecorderDelegate>
/**
The label used to display the current time for recording/playback in the top left
*/
@property (nonatomic, weak) IBOutlet UILabel *currentTimeLabel;
//------------------------------------------------------------------------------
/**
Use a OpenGL based plot to visualize the data coming in
*/
@property (nonatomic,weak) IBOutlet EZAudioPlotGL *audioPlot;
@property (nonatomic, weak) IBOutlet EZAudioPlotGL *recordingAudioPlot;
//------------------------------------------------------------------------------
/**
A flag indicating whether we are recording or not
*/
@property (nonatomic,assign) BOOL isRecording;
@property (nonatomic, assign) BOOL isRecording;
//------------------------------------------------------------------------------
/**
The microphone component
*/
@property (nonatomic,strong) EZMicrophone *microphone;
@property (nonatomic, strong) EZMicrophone *microphone;
//------------------------------------------------------------------------------
/**
The switch used to toggle the microphone on/off
*/
@property (nonatomic, weak) IBOutlet UISwitch *microphoneSwitch;
//------------------------------------------------------------------------------
/**
The label used to display the microphone's play state
*/
@property (nonatomic, weak) IBOutlet UILabel *microphoneStateLabel;
//------------------------------------------------------------------------------
/**
The audio player that will play the recorded file
*/
@property (nonatomic, strong) EZAudioPlayer *player;
//------------------------------------------------------------------------------
/**
The recorder component
*/
@property (nonatomic,strong) EZRecorder *recorder;
@property (nonatomic, strong) EZRecorder *recorder;
//------------------------------------------------------------------------------
/**
The second audio plot used on the top right to display the current playing audio
*/
@property (nonatomic, weak) IBOutlet EZAudioPlot *playingAudioPlot;
//------------------------------------------------------------------------------
/**
The button the user taps to play the recorded audio file
*/
@property (nonatomic, weak) IBOutlet UIButton *playButton;
//------------------------------------------------------------------------------
/**
The label used to display the audio player play state
*/
@property (nonatomic, weak) IBOutlet UILabel *playingStateLabel;
//------------------------------------------------------------------------------
/**
The label used to display the recording play state
*/
@property (nonatomic, weak) IBOutlet UILabel *recordingStateLabel;
//------------------------------------------------------------------------------
/**
The switch used to toggle the recording on/off
*/
@property (nonatomic, weak) IBOutlet UISwitch *recordSwitch;
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
/**
Stops the recorder and starts playing whatever has been recorded.
*/
-(IBAction)playFile:(id)sender;
- (IBAction)playFile:(id)sender;
//------------------------------------------------------------------------------
/**
Toggles the microphone on and off. When the microphone is on it will send its delegate (aka this view controller) the audio data in various ways (check out the EZMicrophoneDelegate documentation for more details);
*/
-(IBAction)toggleMicrophone:(id)sender;
- (IBAction)toggleMicrophone:(id)sender;
//------------------------------------------------------------------------------
/**
Toggles the microphone on and off. When the microphone is on it will send its delegate (aka this view controller) the audio data in various ways (check out the EZMicrophoneDelegate documentation for more details);
*/
-(IBAction)toggleRecording:(id)sender;
- (IBAction)toggleRecording:(id)sender;
@end
@@ -8,53 +8,34 @@
#import "RecordViewController.h"
@interface RecordViewController ()
// Using AVPlayer for example
@property (nonatomic,strong) AVAudioPlayer *audioPlayer;
@property (nonatomic,weak) IBOutlet UISwitch *microphoneSwitch;
@property (nonatomic,weak) IBOutlet UILabel *microphoneTextField;
@property (nonatomic,weak) IBOutlet UIButton *playButton;
@property (nonatomic,weak) IBOutlet UILabel *playingTextField;
@property (nonatomic,weak) IBOutlet UISwitch *recordSwitch;
@property (nonatomic,weak) IBOutlet UILabel *recordingTextField;
@end
@implementation RecordViewController
@synthesize audioPlot;
@synthesize microphone;
@synthesize microphoneSwitch;
@synthesize microphoneTextField;
@synthesize playButton;
@synthesize playingTextField;
@synthesize recorder;
@synthesize recordSwitch;
@synthesize recordingTextField;
//------------------------------------------------------------------------------
#pragma mark - Dealloc
//------------------------------------------------------------------------------
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
//------------------------------------------------------------------------------
#pragma mark - Status Bar Style
//------------------------------------------------------------------------------
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
#pragma mark - Initialization
-(id)init {
self = [super init];
if(self){
[self initializeViewController];
}
return self;
}
//------------------------------------------------------------------------------
#pragma mark - Setup
//------------------------------------------------------------------------------
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self){
[self initializeViewController];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
#pragma mark - Initialize View Controller Here
-(void)initializeViewController {
//
// Setup the AVAudioSession. EZMicrophone will not work properly on iOS
// if you don't do this!
@@ -72,193 +53,277 @@
NSLog(@"Error setting up audio session active: %@", error.localizedDescription);
}
//
// Customizing the audio plot that'll show the current microphone input/recording
//
self.recordingAudioPlot.backgroundColor = [UIColor colorWithRed: 0.984 green: 0.71 blue: 0.365 alpha: 1];
self.recordingAudioPlot.color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
self.recordingAudioPlot.plotType = EZPlotTypeRolling;
self.recordingAudioPlot.shouldFill = YES;
self.recordingAudioPlot.shouldMirror = YES;
//
// Customizing the audio plot that'll show the playback
//
self.playingAudioPlot.color = [UIColor whiteColor];
self.playingAudioPlot.plotType = EZPlotTypeRolling;
self.playingAudioPlot.shouldFill = YES;
self.playingAudioPlot.shouldMirror = YES;
self.playingAudioPlot.gain = 2.5f;
// Create an instance of the microphone and tell it to use this view controller instance as the delegate
self.microphone = [EZMicrophone microphoneWithDelegate:self];
self.player = [EZAudioPlayer audioPlayerWithDelegate:self];
//
// Initialize UI components
//
self.microphoneStateLabel.text = @"Microphone On";
self.recordingStateLabel.text = @"Not Recording";
self.playingStateLabel.text = @"Not Playing";
self.playButton.enabled = NO;
//
// Setup notifications
//
[self setupNotifications];
//
// Log out where the file is being written to within the app's documents directory
//
NSLog(@"File written to application sandbox's documents directory: %@",[self testFilePathURL]);
//
// Start the microphone
//
[self.microphone startFetchingAudio];
}
#pragma mark - Customize the Audio Plot
-(void)viewDidLoad {
[super viewDidLoad];
/*
Customizing the audio plot's look
*/
// Background color
self.audioPlot.backgroundColor = [UIColor colorWithRed: 0.984 green: 0.71 blue: 0.365 alpha: 1];
// Waveform color
self.audioPlot.color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
// Plot type
self.audioPlot.plotType = EZPlotTypeRolling;
// Fill
self.audioPlot.shouldFill = YES;
// Mirror
self.audioPlot.shouldMirror = YES;
/*
Start the microphone
*/
[self.microphone startFetchingAudio];
self.microphoneTextField.text = @"Microphone On";
self.recordingTextField.text = @"Not Recording";
self.playingTextField.text = @"Not Playing";
// Hide the play button
self.playButton.hidden = YES;
/*
Log out where the file is being written to within the app's documents directory
*/
NSLog(@"File written to application sandbox's documents directory: %@",[self testFilePathURL]);
}
//------------------------------------------------------------------------------
#pragma mark - Actions
-(void)playFile:(id)sender
- (void)setupNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerDidChangePlayState:)
name:EZAudioPlayerDidChangePlayStateNotification
object:self.player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerDidReachEndOfFile:)
name:EZAudioPlayerDidReachEndOfFileNotification
object:self.player];
}
//------------------------------------------------------------------------------
#pragma mark - Notifications
//------------------------------------------------------------------------------
- (void)playerDidChangePlayState:(NSNotification *)notification
{
EZAudioPlayer *player = [notification object];
BOOL isPlaying = [player isPlaying];
if (isPlaying)
{
self.recorder.delegate = nil;
}
self.playingStateLabel.text = isPlaying ? @"Playing" : @"Not Playing";
self.playingAudioPlot.hidden = !isPlaying;
}
//------------------------------------------------------------------------------
- (void)playerDidReachEndOfFile:(NSNotification *)notification
{
[self.playingAudioPlot clear];
}
//------------------------------------------------------------------------------
#pragma mark - Actions
//------------------------------------------------------------------------------
- (void)playFile:(id)sender
{
//
// Update microphone state
//
[self.microphone stopFetchingAudio];
self.microphoneTextField.text = @"Microphone Off";
self.microphoneSwitch.on = NO;
//
// Update recording state
//
self.isRecording = NO;
self.recordingTextField.text = @"Not Recording";
self.recordingStateLabel.text = @"Not Recording";
self.recordSwitch.on = NO;
// Create Audio Player
if( self.audioPlayer )
{
if( self.audioPlayer.playing )
{
[self.audioPlayer stop];
}
self.audioPlayer = nil;
}
//
// Close the audio file
if( self.recorder )
//
if (self.recorder)
{
[self.recorder closeAudioFile];
}
NSError *err;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[self testFilePathURL]
error:&err];
[self.audioPlayer play];
self.audioPlayer.delegate = self;
self.playingTextField.text = @"Playing";
EZAudioFile *audioFile = [EZAudioFile audioFileWithURL:[self testFilePathURL]];
[self.player playAudioFile:audioFile];
}
-(void)toggleMicrophone:(id)sender {
self.playingTextField.text = @"Not Playing";
if( self.audioPlayer ){
if( self.audioPlayer.playing ) [self.audioPlayer stop];
self.audioPlayer = nil;
}
if( ![(UISwitch*)sender isOn] ){
[self.microphone stopFetchingAudio];
self.microphoneTextField.text = @"Microphone Off";
}
else {
[self.microphone startFetchingAudio];
self.microphoneTextField.text = @"Microphone On";
}
}
//------------------------------------------------------------------------------
-(void)toggleRecording:(id)sender {
self.playingTextField.text = @"Not Playing";
if( self.audioPlayer )
{
if( self.audioPlayer.playing )
{
[self.audioPlayer stop];
}
self.audioPlayer = nil;
}
self.playButton.hidden = NO;
- (void)toggleMicrophone:(id)sender
{
[self.player pause];
if( [sender isOn] )
BOOL isOn = [(UISwitch*)sender isOn];
if (!isOn)
{
/*
Create the recorder
*/
[EZAudioUtilities printASBD:self.microphone.audioStreamBasicDescription];
self.recorder = [EZRecorder recorderWithDestinationURL:[self testFilePathURL]
sourceFormat:self.microphone.audioStreamBasicDescription
destinationFileType:EZRecorderFileTypeM4A];
[self.microphone stopFetchingAudio];
}
else
{
[self.recorder closeAudioFile];
[self.microphone startFetchingAudio];
}
}
//------------------------------------------------------------------------------
- (void)toggleRecording:(id)sender
{
[self.player pause];
if ([sender isOn])
{
//
// Create the recorder
//
[self.recordingAudioPlot clear];
[self.microphone startFetchingAudio];
self.recorder = [EZRecorder recorderWithURL:[self testFilePathURL]
clientFormat:[self.microphone audioStreamBasicDescription]
fileType:EZRecorderFileTypeM4A
delegate:self];
self.playButton.enabled = YES;
}
self.isRecording = (BOOL)[sender isOn];
self.recordingTextField.text = self.isRecording ? @"Recording" : @"Not Recording";
self.recordingStateLabel.text = self.isRecording ? @"Recording" : @"Not Recording";
}
//------------------------------------------------------------------------------
#pragma mark - EZMicrophoneDelegate
//------------------------------------------------------------------------------
- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying
{
self.microphoneStateLabel.text = isPlaying ? @"Microphone On" : @"Microphone Off";
self.microphoneSwitch.on = isPlaying;
}
//------------------------------------------------------------------------------
#warning Thread Safety
// Note that any callback that provides streamed audio data (like streaming microphone input) happens on a separate audio thread that should not be blocked. When we feed audio data into any of the UI components we need to explicity create a GCD block on the main thread to properly get the UI to work.
-(void)microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels {
// Getting audio data as an array of float buffer arrays. What does that mean? Because the audio is coming in as a stereo signal the data is split into a left and right channel. So buffer[0] corresponds to the float* data for the left channel while buffer[1] corresponds to the float* data for the right channel.
- (void) microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
{
// Getting audio data as an array of float buffer arrays. What does that mean? Because the audio is coming in as a stereo signal the data is split into a left and right channel. So buffer[0] corresponds to the float* data for the left channel while buffer[1] corresponds to the float* data for the right channel.
// See the Thread Safety warning above, but in a nutshell these callbacks happen on a separate audio thread. We wrap any UI updating in a GCD block on the main thread to avoid blocking that audio flow.
dispatch_async(dispatch_get_main_queue(),^{
// All the audio plot needs is the buffer data (float*) and the size. Internally the audio plot will handle all the drawing related code, history management, and freeing its own resources. Hence, one badass line of code gets you a pretty plot :)
[self.audioPlot updateBuffer:buffer[0] withBufferSize:bufferSize];
});
// See the Thread Safety warning above, but in a nutshell these callbacks happen on a separate audio thread. We wrap any UI updating in a GCD block on the main thread to avoid blocking that audio flow.
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
// All the audio plot needs is the buffer data (float*) and the size. Internally the audio plot will handle all the drawing related code, history management, and freeing its own resources. Hence, one badass line of code gets you a pretty plot :)
[weakSelf.recordingAudioPlot updateBuffer:buffer[0]
withBufferSize:bufferSize];
});
}
-(void)microphone:(EZMicrophone *)microphone
hasBufferList:(AudioBufferList *)bufferList
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels {
// Getting audio data as a buffer list that can be directly fed into the EZRecorder. This is happening on the audio thread - any UI updating needs a GCD main queue block. This will keep appending data to the tail of the audio file.
if( self.isRecording ){
[self.recorder appendDataFromBufferList:bufferList
withBufferSize:bufferSize];
}
//------------------------------------------------------------------------------
- (void) microphone:(EZMicrophone *)microphone
hasBufferList:(AudioBufferList *)bufferList
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
{
// Getting audio data as a buffer list that can be directly fed into the EZRecorder. This is happening on the audio thread - any UI updating needs a GCD main queue block. This will keep appending data to the tail of the audio file.
if (self.isRecording)
{
[self.recorder appendDataFromBufferList:bufferList
withBufferSize:bufferSize];
}
}
#pragma mark - AVAudioPlayerDelegate
/*
Occurs when the audio player instance completes playback
*/
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
self.audioPlayer = nil;
self.playingTextField.text = @"Finished Playing";
[self.microphone startFetchingAudio];
self.microphoneSwitch.on = YES;
self.microphoneTextField.text = @"Microphone On";
//------------------------------------------------------------------------------
#pragma mark - EZRecorderDelegate
//------------------------------------------------------------------------------
- (void)recorderDidClose:(EZRecorder *)recorder
{
recorder.delegate = nil;
}
//------------------------------------------------------------------------------
- (void)recorderUpdatedCurrentTime:(EZRecorder *)recorder
{
__weak typeof (self) weakSelf = self;
NSString *formattedCurrentTime = [recorder formattedCurrentTime];
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.currentTimeLabel.text = formattedCurrentTime;
});
}
//------------------------------------------------------------------------------
#pragma mark - EZAudioPlayerDelegate
//------------------------------------------------------------------------------
- (void) audioPlayer:(EZAudioPlayer *)audioPlayer
playedAudio:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels
inAudioFile:(EZAudioFile *)audioFile
{
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.playingAudioPlot updateBuffer:buffer[0]
withBufferSize:bufferSize];
});
}
//------------------------------------------------------------------------------
- (void)audioPlayer:(EZAudioPlayer *)audioPlayer
updatedPosition:(SInt64)framePosition
inAudioFile:(EZAudioFile *)audioFile
{
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.currentTimeLabel.text = [audioPlayer formattedCurrentTime];
});
}
//------------------------------------------------------------------------------
#pragma mark - Utility
-(NSArray*)applicationDocuments {
//------------------------------------------------------------------------------
- (NSArray *)applicationDocuments
{
return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
}
-(NSString*)applicationDocumentsDirectory
//------------------------------------------------------------------------------
- (NSString *)applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
-(NSURL*)testFilePathURL {
return [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",
[self applicationDocumentsDirectory],
kAudioFilePath]];
//------------------------------------------------------------------------------
- (NSURL *)testFilePathURL
{
return [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",
[self applicationDocumentsDirectory],
kAudioFilePath]];
}
@end
@end
@@ -25,6 +25,7 @@
667559951B3B78820013E67E /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 667559801B3B78820013E67E /* TPCircularBuffer.c */; };
667559961B3B78820013E67E /* CHANGELOG in Resources */ = {isa = PBXBuildFile; fileRef = 667559831B3B78820013E67E /* CHANGELOG */; };
667559971B3B78820013E67E /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 667559841B3B78820013E67E /* VERSION */; };
667EEA4B1B51EF6600D57FB2 /* EZAudioFFT.m in Sources */ = {isa = PBXBuildFile; fileRef = 667EEA4A1B51EF6600D57FB2 /* EZAudioFFT.m */; };
9405705E185E69D400EB94BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9405705D185E69D400EB94BA /* Foundation.framework */; };
94057060185E69D400EB94BA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9405705F185E69D400EB94BA /* CoreGraphics.framework */; };
94057062185E69D400EB94BA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94057061185E69D400EB94BA /* UIKit.framework */; };
@@ -88,6 +89,8 @@
667559811B3B78820013E67E /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = "<group>"; };
667559831B3B78820013E67E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = "<group>"; };
667559841B3B78820013E67E /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
667EEA491B51EF6600D57FB2 /* EZAudioFFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZAudioFFT.h; sourceTree = "<group>"; };
667EEA4A1B51EF6600D57FB2 /* EZAudioFFT.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZAudioFFT.m; sourceTree = "<group>"; };
9405705A185E69D400EB94BA /* EZAudioWaveformFromFileExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EZAudioWaveformFromFileExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
9405705D185E69D400EB94BA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
9405705F185E69D400EB94BA /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@@ -148,6 +151,8 @@
667559651B3B78820013E67E /* EZAudioDevice.m */,
667559661B3B78820013E67E /* EZAudioDisplayLink.h */,
667559671B3B78820013E67E /* EZAudioDisplayLink.m */,
667EEA491B51EF6600D57FB2 /* EZAudioFFT.h */,
667EEA4A1B51EF6600D57FB2 /* EZAudioFFT.m */,
667559681B3B78820013E67E /* EZAudioFile.h */,
667559691B3B78820013E67E /* EZAudioFile.m */,
6675596A1B3B78820013E67E /* EZAudioFloatConverter.h */,
@@ -369,6 +374,7 @@
6675598C1B3B78820013E67E /* EZAudioPlayer.m in Sources */,
9405706E185E69D400EB94BA /* AppDelegate.m in Sources */,
6675598E1B3B78820013E67E /* EZAudioPlotGL.m in Sources */,
667EEA4B1B51EF6600D57FB2 /* EZAudioFFT.m in Sources */,
667559891B3B78820013E67E /* EZAudioFile.m in Sources */,
667559921B3B78820013E67E /* EZOutput.m in Sources */,
667559901B3B78820013E67E /* EZAudioUtilities.m in Sources */,
@@ -506,6 +512,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioWaveformFromFileExample/EZAudioWaveformFromFileExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioWaveformFromFileExample/EZAudioWaveformFromFileExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -519,6 +526,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "EZAudioWaveformFromFileExample/EZAudioWaveformFromFileExample-Prefix.pch";
INFOPLIST_FILE = "EZAudioWaveformFromFileExample/EZAudioWaveformFromFileExample-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7702" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="d7h-J5-hmC">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="d7h-J5-hmC">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<scenes>
<!--Waveform From File View Controller-->
+752 -235
View File
File diff suppressed because it is too large Load Diff