The docs for AudioComponentDescription say that componentFlags and
componentFlagsMask must be set to 0 unless specific values are
requested.
Different platforms (32 vs 64 bit) initialize data to different starting
values. Ensure the AudioComponentDescription is initialized to prevent
unwanted side effects.
A simple, intuitive audio framework for iOS and OSX.
## Welcome to 1.0.0!
Thank you guys for being so patient over the last year - I've been working like crazy the last few weeks rewriting and extending the EZAudio core and interface components and squashing bugs. Finally, EZAudio is now at its 1.0.0 release with all new updated components, examples, and documentation. Happy coding!
## Deprecated
EZAudio has recently been deprecated in favor of AudioKit. However, since some people are still forking and using EZAudio I've decided to restore the README as it was. [Check out the note below](#Deprecated).
## Apps Using EZAudio
I'd really like to start creating a list of projects made using EZAudio. If you've used EZAudio to make something cool, whether it's an app or open source visualization or whatever, please email me at syedhali07[at]gmail.com and I'll add it to our wall of fame!
@@ -53,7 +59,7 @@ An OpenGL-based, GPU-accelerated audio waveform plot capable of visualizing any
`EZAudio` was designed to work transparently across all iOS and OSX devices. This means one universal API whether you're building for Mac or iOS. For instance, under the hood an `EZAudioPlot` knows that it will subclass a UIView for iOS or an NSView for OSX and the `EZMicrophone` knows to build on top of the RemoteIO AudioUnit for iOS, but defaults to the system defaults for input and output for OSX.
##<a name="Examples">Examples & Docs
##<a name="Examples">Examples & Docs
Within this repo you'll find the examples for iOS and OSX to get you up to speed using each component and plugging them into each other. With just a few lines of code you'll be recording from the microphone, generating audio waveforms, and playing audio files like a boss. See the full Getting Started guide for an interactive look into each of components.
@@ -102,20 +108,20 @@ Shows how to use the `EZMicrophone`, `EZOutput`, and the `EZAudioPlotGL` to pass
Shows how to calculate the real-time FFT of the audio data coming from the `EZMicrophone` and the Accelerate framework. The audio data is plotted using two `EZAudioPlots` for the time and frequency displays.
### Documentation
The official documentation for EZAudio can be found here: http://cocoadocs.org/docsets/EZAudio/1.1.3/
The official documentation for EZAudio can be found here: http://cocoadocs.org/docsets/EZAudio/1.1.4/
<br>You can also generate the docset yourself using appledocs by running the appledocs on the EZAudio source folder.
##<a name="GettingStarted">Getting Started
##<a name="GettingStarted">Getting Started
To begin using `EZAudio` you must first make sure you have the proper build requirements and frameworks. Below you'll find explanations of each component and code snippets to show how to use each to perform common tasks like getting microphone data, updating audio waveform plots, reading/seeking through audio files, and performing playback.
###Build Requirements
###Build Requirements
**iOS**
- 6.0+
**OSX**
- 10.8+
###Frameworks
###Frameworks
**iOS**
- Accelerate
- AudioToolbox
@@ -131,18 +137,18 @@ To begin using `EZAudio` you must first make sure you have the proper build requ
- OpenGL
- GLKit
###<a name="AddingToProject">Adding To Project
###<a name="AddingToProject">Adding To Project
You can add EZAudio to your project in a few ways: <br><br>1.) The easiest way to use EZAudio is via <a href="http://cocoapods.org/", target="_blank">Cocoapods</a>. Simply add EZAudio to your <a href="http://guides.cocoapods.org/using/the-podfile.html", target="_blank">Podfile</a> like so:
`
pod 'EZAudio', '~> 1.1.3'
pod 'EZAudio', '~> 1.1.4'
`
####<a name="AmazingAudioEngineCocoapod">Using EZAudio & The Amazing Audio Engine
####<a name="AmazingAudioEngineCocoapod">Using EZAudio & The Amazing Audio Engine
If you're also using the Amazing Audio Engine then use the `EZAudio/Core` subspec like so:
`
pod 'EZAudio/Core', '~> 1.1.3'
pod 'EZAudio/Core', '~> 1.1.4'
`
2.) EZAudio now supports Carthage (thanks Andrew and Tommaso!). You can refer to Carthage's installation for a how-to guide:
3.) Alternatively, you can check out the iOS/Mac examples for how to setup a project using the EZAudio project as an embedded project and utilizing the frameworks. Be sure to set your header search path to the folder containing the EZAudio source.
##<a name="CoreComponents"></a>Core Components
##<a name="CoreComponents"></a>Core Components
`EZAudio` currently offers six audio components that encompass a wide range of functionality. In addition to the functional aspects of these components such as pulling audio data, reading/writing from files, and performing playback they also take special care to hook into the interface components to allow developers to display visual feedback (see the [Interface Components](#InterfaceComponents) below).
###<a name="EZAudioDevice"></a>EZAudioDevice
###<a name="EZAudioDevice"></a>EZAudioDevice
Provides a simple interface for obtaining the current and all available inputs and output for any Apple device. For instance, the iPhone 6 has three microphones available for input, while on OSX you can choose the Built-In Microphone or any available HAL device on your system. Similarly, for iOS you can choose from a pair of headphones connected or speaker, while on OSX you can choose from the Built-In Output, any available HAL device, or Airplay.
Provides access to the default device microphone in one line of code and provides delegate callbacks to receive the audio data as an AudioBufferList and float arrays.
**_Relevant Example Projects_**
@@ -200,7 +206,7 @@ Provides access to the default device microphone in one line of code and provide
- EZAudioFFTExample (iOS)
- EZAudioFFTExample (OSX)
####Creating A Microphone
####Creating A Microphone
Create an `EZMicrophone` instance by declaring a property and initializing it like so:
@@ -221,7 +227,7 @@ Alternatively, you could also use the shared `EZMicrophone` instance and just as
[EZMicrophonesharedMicrophone].delegate=self;
```
####Setting The Device
####Setting The Device
The `EZMicrophone` uses an `EZAudioDevice` instance to select what specific hardware destination it will use to pull audio data. You'd use this if you wanted to change the input device like in the EZAudioCoreGraphicsWaveformExample for [iOS](https://github.com/syedhali/EZAudio/tree/master/EZAudioExamples/iOS/EZAudioCoreGraphicsWaveformExample) or [OSX](https://github.com/syedhali/EZAudio/tree/master/EZAudioExamples/OSX/EZAudioCoreGraphicsWaveformExample). At any time you can change which input device is used by setting the device property:
```objectivec
NSArray*inputs=[EZAudioDeviceinputDevices];
@@ -243,7 +249,7 @@ Anytime the `EZMicrophone` changes its device it will trigger the `EZMicrophoneD
```
**Note: For iOS this can happen automatically if the AVAudioSession changes the current device.**
####Getting Microphone Data
####Getting Microphone Data
To tell the microphone to start fetching audio use the `startFetchingAudio` function.
@@ -291,7 +297,7 @@ or the AudioBufferList representation:
// or EZOutput. Say whattt...
}
```
####Pausing/Resuming The Microphone
####Pausing/Resuming The Microphone
Pause or resume fetching audio at any time like so:
Provides flexible playback to the default output device by asking the `EZOutputDataSource` for audio data to play. Doesn't care where the buffers come from (microphone, audio file, streaming audio, etc). As of 1.0.0 the `EZOutputDataSource` has been simplified to have only one method to provide audio data to your `EZOutput` instance.
```objectivec
// The EZOutputDataSource should fill out the audioBufferList with the given frame count.
@@ -329,7 +335,7 @@ Provides flexible playback to the default output device by asking the `EZOutputD
- EZAudioPassThroughExample (iOS)
- EZAudioPassThroughExample (OSX)
####Creating An Output
####Creating An Output
Create an `EZOutput` by declaring a property and initializing it like so:
@@ -346,7 +352,7 @@ Alternatively, you could also use the shared output instance and just assign it
// Assign a delegate to the shared instance of the output to provide the output audio data
[EZOutputsharedOutput].delegate=self;
```
####Setting The Device
####Setting The Device
The `EZOutput` uses an `EZAudioDevice` instance to select what specific hardware destination it will output audio to. You'd use this if you wanted to change the output device like in the [EZAudioPlayFileExample](https://github.com/syedhali/EZAudio/tree/master/EZAudioExamples/OSX/EZAudioPlayFileExample) for OSX. At any time you can change which output device is used by setting the `device` property:
```objectivec
// By default the EZOutput uses the default output device, but you can change this at any time
@@ -362,9 +368,9 @@ Anytime the `EZOutput` changes its device it will trigger the `EZOutputDelegate`
}
```
####Playing Audio
####Playing Audio
#####Setting The Input Format
#####Setting The Input Format
When providing audio data the `EZOutputDataSource` will expect you to fill out the AudioBufferList provided with whatever `inputFormat` that is set on the `EZOutput`. By default the input format is a stereo, non-interleaved, float format (see [defaultInputFormat](http://cocoadocs.org/docsets/EZAudio/1.1.2/Classes/EZOutput.html#//api/name/defaultInputFormat) for more information). If you're dealing with a different input format (which is typically the case), just set the `inputFormat` property. For instance:
```objectivec
@@ -372,7 +378,7 @@ When providing audio data the `EZOutputDataSource` will expect you to fill out t
An example of implementing the `EZOutputDataSource` is done internally in the `EZAudioPlayer` using an `EZAudioFile` to read audio from an audio file on disk like so:
```objectivec
@@ -477,7 +483,7 @@ An array of float arrays:
}
```
####Pausing/Resuming The Output
####Pausing/Resuming The Output
Pause or resume the output component at any time like so:
```objectivec
// Stop fetching audio
@@ -487,7 +493,7 @@ Pause or resume the output component at any time like so:
[self.outputstartPlayback];
```
####Chaining Audio Unit Effects
####Chaining Audio Unit Effects
Internally the `EZOutput` is using an AUGraph to chain together a converter, mixer, and output audio units. You can hook into this graph by subclassing `EZOutput` and implementing the method:
```objectivec
// By default this method connects the AUNode representing the input format converter to
@@ -562,14 +568,14 @@ Here's an example of how to add a delay audio unit (`kAudioUnitSubType_Delay`):
}
```
###<a name="EZAudioFile"></a>EZAudioFile
###<a name="EZAudioFile"></a>EZAudioFile
Provides simple read/seek operations, pulls waveform amplitude data, and provides the `EZAudioFileDelegate` to notify of any read/seek action occuring on the `EZAudioFile`. This can be thought of as the NSImage/UIImage equivalent of the audio world.
**_Relevant Example Projects_**
- EZAudioWaveformFromFileExample (iOS)
- EZAudioWaveformFromFileExample (OSX)
####Opening An Audio File
####Opening An Audio File
To open an audio file create a new instance of the `EZAudioFile` class.
```objectivec
// Declare the EZAudioFile as a strong property
@@ -581,7 +587,7 @@ To open an audio file create a new instance of the `EZAudioFile` class.
Reading audio data from a file requires you to create an AudioBufferList to hold the data. The `EZAudio` utility function, `audioBufferList`, provides a convenient way to get an allocated AudioBufferList to use. There is also a utility function, `freeBufferList:`, to use to free (or release) the AudioBufferList when you are done using that audio data.
@@ -650,7 +656,7 @@ and an event notifying the delegate of the new frame position within the `EZAudi
}
```
####Seeking Through An Audio File
####Seeking Through An Audio File
You can seek very easily through an audio file using the `EZAudioFile`'s seekToFrame: method. The `EZAudioFile` provides a `totalFrames` method to provide you the total amount of frames in an audio file so you can calculate a proper offset.
```objectivec
@@ -675,10 +681,10 @@ When a seek occurs the `EZAudioFileDelegate` receives the seek event:
}
```
###<a name="EZAudioPlayer"></a>EZAudioPlayer
###<a name="EZAudioPlayer"></a>EZAudioPlayer
Provides a class that combines the `EZAudioFile` and `EZOutput` for file playback of all Core Audio supported formats to any hardware device. Because the `EZAudioPlayer` internally hooks into the `EZAudioFileDelegate` and `EZOutputDelegate`, you should implement the `EZAudioPlayerDelegate` to receive the `playedAudio:...` and `updatedPosition:` events. The EZAudioPlayFileExample projects for [iOS](https://github.com/syedhali/EZAudio/tree/master/EZAudioExamples/iOS/EZAudioPlayFileExample) and [OSX](https://github.com/syedhali/EZAudio/tree/master/EZAudioExamples/OSX/EZAudioPlayFileExample) shows how to use the `EZAudioPlayer` to play audio files, visualize the samples with an audio plot, adjust the volume, and change the output device using the `EZAudioDevice` class. The `EZAudioPlayer` primarily uses `NSNotificationCenter` to post notifications because often times you have one audio player and multiple UI elements that need to listen for player events to properly update.
####Creating An Audio Player
####Creating An Audio Player
```objectivec
// Declare the EZAudioFile as a strong property
@property(nonatomic,strong)EZAudioFile*audioFile;
@@ -689,7 +695,7 @@ Provides a class that combines the `EZAudioFile` and `EZOutput` for file playbac
The `EZAudioPlayer` uses an internal `EZAudioFile` to provide data to its `EZOutput` for output via the `EZOutputDataSource`. You can provide an `EZAudioFile` by just setting the `audioFile` property on the `EZAudioPlayer` will make a copy of the `EZAudioFile` at that file path url for its own use.
```objectivec
// Set the EZAudioFile for playback by setting the `audioFile` property
@@ -739,7 +745,7 @@ As audio is played the `EZAudioPlayerDelegate` will receive the `playedAudio:...
}
```
####Seeking
####Seeking
You can seek through the audio file in a similar fashion as with the `EZAudioFile`. That is, using the `seekToFrame:` or `currentTime` property.
```objectivec
// Get the total number of frames and seek halfway
Because the `EZAudioPlayer` wraps the `EZOutput` you can adjust the volume and pan parameters for playback.
```objectivec
// Make it half as loud, 0 = silence, 1 = full volume. Default is 1.
@@ -761,7 +767,7 @@ Because the `EZAudioPlayer` wraps the `EZOutput` you can adjust the volume and p
[self.playersetPan:-1.0];
```
####Getting Audio File Parameters
####Getting Audio File Parameters
The `EZAudioPlayer` wraps the `EZAudioFile` and provides a high level interface for pulling values like current time, duration, the frame index, total frames, etc.
Provides a way to record any audio source to an audio file. This hooks into the other components quite nicely to do something like plot the audio waveform while recording to give visual feedback as to what is happening. The `EZRecorderDelegate` provides methods to listen to write events and a final close event on the `EZRecorder` (explained [below](#EZRecorderDelegateExplanation)).
*Relevant Example Projects*
- EZAudioRecordExample (iOS)
- EZAudioRecordExample (OSX)
####Creating A Recorder
####Creating A Recorder
To create an `EZRecorder` you must provide at least 3 things: an NSURL representing the file path of where the audio file should be written to (an existing file will be overwritten), a `clientFormat` representing the format in which you will be providing the audio data, and either an `EZRecorderFileType` or an `AudioStreamBasicDescription` representing the file format of the audio data on disk.
Once you've initialized your `EZRecorder` you can append data by passing in an AudioBufferList and its buffer size like so:
```objectivec
@@ -902,7 +908,7 @@ Once you've initialized your `EZRecorder` you can append data by passing in an A
}
```
#####<a name="EZRecorderDelegateExplanation"></a>Responding to an EZRecorder after it has written audio data
#####<a name="EZRecorderDelegateExplanation"></a>Responding to an EZRecorder after it has written audio data
Once audio data has been successfully written with the `EZRecorder` it will notify the `EZRecorderDelegate` of the event so it can respond via:
```objectivec
@@ -923,7 +929,7 @@ Once audio data has been successfully written with the `EZRecorder` it will noti
}
```
####Closing An Audio File
####Closing An Audio File
When you're recording is done be sure to call the `closeAudioFile` method to make sure the audio file written to disk is properly closed before you attempt to read it again.
```objectivec
@@ -939,10 +945,10 @@ This will trigger the EZRecorder's delegate method:
`EZAudio` currently offers two drop in audio waveform components that help simplify the process of visualizing audio.
###<a name="EZAudioPlot"></a>EZAudioPlot
###<a name="EZAudioPlot"></a>EZAudioPlot
Provides an audio waveform plot that uses CoreGraphics to perform the drawing. On iOS this is a subclass of UIView while on OSX this is a subclass of NSView. As of the 1.0.0 release, the waveforms are drawn using CALayers where compositing is done on the GPU. As a result, there have been some huge performance gains and CPU usage per real-time (i.e. 60 frames per second redrawing) plot is now about 2-3% CPU as opposed to the 20-30% we were experiencing before.
*Relevant Example Projects*
@@ -955,7 +961,7 @@ Provides an audio waveform plot that uses CoreGraphics to perform the drawing. O
- EZAudioFFTExample (iOS)
- EZAudioFFTExample (OSX)
####Creating An Audio Plot
####Creating An Audio Plot
You can create an audio plot in the interface builder by dragging in a UIView on iOS or an NSView on OSX onto your content area. Then change the custom class of the UIView/NSView to `EZAudioPlot`.
All plots offer the ability to change the background color, waveform color, plot type (buffer or rolling), toggle between filled and stroked, and toggle between mirrored and unmirrored (about the x-axis). For iOS colors are of the type UIColor while on OSX colors are of the type NSColor.
@@ -992,13 +998,13 @@ audioPlot.shouldFill = YES;
audioPlot.shouldMirror=YES;
```
####IBInspectable Attributes
####IBInspectable Attributes
Also, as of iOS 8 you can adjust the background color, color, gain, shouldFill, and shouldMirror parameters directly in the Interface Builder via the IBInspectable attributes:
All plots have only one update function, `updateBuffer:withBufferSize:`, which expects a float array and its length.
```objectivec
@@ -1022,7 +1028,7 @@ All plots have only one update function, `updateBuffer:withBufferSize:`, which e
}
```
###<a name="EZAudioPlotGL"></a>EZAudioPlotGL
###<a name="EZAudioPlotGL"></a>EZAudioPlotGL
Provides an audio waveform plot that uses OpenGL to perform the drawing. The API this class are exactly the same as those for the EZAudioPlot above. On iOS this is a subclass of the GLKView while on OSX this is a subclass of the NSOpenGLView. In most cases this is the plot you want to use, it's GPU-accelerated, can handle lots of points while displaying 60 frames per second (the EZAudioPlot starts to choke on anything greater than 1024), and performs amazingly on all devices. The only downside is that you can only have one OpenGL plot onscreen at a time. However, you can combine OpenGL plots with Core Graphics plots in the view hierachy (see the EZAudioRecordExample for an example of how to do this).
*Relevant Example Projects*
@@ -1035,7 +1041,7 @@ Provides an audio waveform plot that uses OpenGL to perform the drawing. The API
- EZAudioPassThroughExample (iOS)
- EZAudioPassThroughExample (OSX)
####Creating An OpenGL Audio Plot
####Creating An OpenGL Audio Plot
You can create an audio plot in the interface builder by dragging in a UIView on iOS or an NSView on OSX onto your content area. Then change the custom class of the UIView/NSView to `EZAudioPlotGL`.
All plots offer the ability to change the background color, waveform color, plot type (buffer or rolling), toggle between filled and stroked, and toggle between mirrored and unmirrored (about the x-axis). For iOS colors are of the type UIColor while on OSX colors are of the type NSColor.
Also, as of iOS 8 you can adjust the background color, color, gain, shouldFill, and shouldMirror parameters directly in the Interface Builder via the IBInspectable attributes:
All plots have only one update function, `updateBuffer:withBufferSize:`, which expects a float array and its length.
```objectivec
@@ -1100,18 +1106,42 @@ All plots have only one update function, `updateBuffer:withBufferSize:`, which e
}
```
##License
##License
EZAudio is available under the MIT license. See the LICENSE file for more info.
##Contact & Contributers
##Contact & Contributers
Syed Haris Ali<br>
www.syedharisali.com<br>
syedhali07[at]gmail.com
##Acknowledgements
##Acknowledgements
The following people rock:
- My brother, [Reza Ali](http://www.syedrezaali.com/), for walking me through all the gritty details of OpenGL and his constant encouragement through this journey to 1.0.0.
- [Aure Prochazka](http://aure.com/) for his amazing work on [AudioKit](http://audiokit.io/) and his encouragement to bring EZAudio to 1.0.0
- [Daniel Kennett](http://ikennd.ac/) for writing [this great blog post](http://ikennd.ac/blog/2012/04/augraph-basics-in-cocoalibspotify/) that inspired the rewrite of the `EZOutput` in 1.0.0.
- [Michael Tyson](http://atastypixel.com/blog/) for creating the [TPCircularBuffer](http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/) and all his contributions to the community including the Amazing Audio Engine, Audiobus, and all the tasty pixel blog posts.
- Chris Adamson and Kevin Avila for writing the amazing [Learning Core Audio](http://www.amazon.com/Learning-Core-Audio-Hands-On-Programming/dp/0321636848) book.
As of today, June 13, 2016, I’m officially deprecating EZAudio. I’d like to thank everyone for the support over the last few years I’ve been hacking on EZAudio and working to make it better.
### Alternatives
The best alternative to EZAudio is now [AudioKit](http://audiokit.io/). Note that [The Amazing Audio Engine](https://github.com/TheAmazingAudioEngine/TheAmazingAudioEngine) and [The Amazing Audio Engine 2](https://github.com/TheAmazingAudioEngine/TheAmazingAudioEngine2) have now both been retired as well. Any further contributions I make to iOS/macOS/tvOS audio programming will be to AudioKit.
EZAudio started as a pet project of mine in 2013 in an attempt to reduce the amount of duplicate code I was writing for my own iOS/Mac audio projects. I originally just wanted to record audio from an iPhone’s mic and plot a waveform. This over time quickly grew into the collection of classes you may know today (EZMicrophone, EZAudioPlot, etc).
I apologize for not being more active in addressing the issues and pull requests, but I’m hoping you all understand I’m only one person. EZAudio was solely written and maintained by me out of love during weeks of time I wasn’t making any money, all while living in one of the most expensive cities in the world. Like many of you, I spend the majority of my time working full-time to sustain myself (I have bills and rent to pay too!). I’m transitioning to non-audio ventures and will hopefully be able to share another cool open source project soon enough.
Getting the opportunity to work on EZAudio with all of you has been an incredibly insightful experience and I’m incredibly grateful to have gotten a chance to share it with all of you. Thank you.
### Is all of it broken?
As I’m writing this I’m a little hesitant to say it’s all broken (despite all the issues filed), but I’d recommend forking this repo from this point forward and using at your own risk. I’ll probably be continuing to use EZAudio’s EZAudioPlot forrendering waveforms in my future projects, however, please don’t expect any updates to this repo. Deprecated means I won’t be responding to issues, EZAudio-related emails, or pushing any new changes to this repo.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.