├── .gitmodules ├── Podfile ├── .gitignore ├── Sounds ├── crick.caf ├── hihat.caf ├── kick.caf └── woodblock.caf ├── AmazingSequencer ├── en.lproj │ └── InfoPlist.strings ├── WelcomeVC.h ├── SimpleDemoVC.h ├── AppDelegate.h ├── AmazingSequencer-Prefix.pch ├── main.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── SequencerButton.h ├── AppDelegate.m ├── SequencerButton.m ├── AESequencerChannel.h ├── AmazingSequencer-Info.plist ├── AESequencerBeat.m ├── AESequencerBeat.h ├── AESequencerChannelSequence.h ├── AESequencerChannelSequence.m ├── WelcomeVC.m └── SimpleDemoVC.m ├── AmazingSequencerTests ├── en.lproj │ └── InfoPlist.strings ├── AmazingSequencerTests-Info.plist └── AmazingSequencerTests.m ├── Pods ├── Headers │ ├── Build │ │ └── TheAmazingAudioEngine │ │ │ ├── AELimiter.h │ │ │ ├── AERecorder.h │ │ │ ├── AEMixerBuffer.h │ │ │ ├── AEExpanderFilter.h │ │ │ ├── AELimiterFilter.h │ │ │ ├── AEUtilities.h │ │ │ ├── AEBlockChannel.h │ │ │ ├── AEBlockFilter.h │ │ │ ├── AEPlaythroughChannel.h │ │ │ ├── AEAudioController.h │ │ │ ├── AEAudioFilePlayer.h │ │ │ ├── AEAudioFileWriter.h │ │ │ ├── AEAudioUnitFilter.h │ │ │ ├── AEBlockScheduler.h │ │ │ ├── AEFloatConverter.h │ │ │ ├── AEAudioUnitChannel.h │ │ │ ├── AEBlockAudioReceiver.h │ │ │ ├── TheAmazingAudioEngine.h │ │ │ ├── AEAudioController+Audiobus.h │ │ │ ├── AEAudioFileLoaderOperation.h │ │ │ ├── AEAudioController+AudiobusStub.h │ │ │ ├── TPCircularBuffer.h │ │ │ └── TPCircularBuffer+AudioBufferList.h │ └── Public │ │ └── TheAmazingAudioEngine │ │ ├── AELimiter.h │ │ ├── AERecorder.h │ │ ├── AEMixerBuffer.h │ │ ├── AEExpanderFilter.h │ │ ├── AELimiterFilter.h │ │ ├── AEUtilities.h │ │ ├── AEBlockChannel.h │ │ ├── AEBlockFilter.h │ │ ├── AEPlaythroughChannel.h │ │ ├── AEAudioController.h │ │ ├── AEAudioFilePlayer.h │ │ ├── AEAudioFileWriter.h │ │ ├── AEAudioUnitFilter.h │ │ ├── AEBlockScheduler.h │ │ ├── AEFloatConverter.h │ │ ├── AEAudioUnitChannel.h │ │ ├── AEBlockAudioReceiver.h │ │ ├── TheAmazingAudioEngine.h │ │ ├── AEAudioController+Audiobus.h │ │ ├── AEAudioFileLoaderOperation.h │ │ ├── TPCircularBuffer.h │ │ ├── AEAudioController+AudiobusStub.h │ │ └── TPCircularBuffer+AudioBufferList.h ├── Target Support Files │ ├── Pods │ │ ├── Pods-dummy.m │ │ ├── Pods.debug.xcconfig │ │ ├── Pods.release.xcconfig │ │ ├── Pods-environment.h │ │ ├── Pods-acknowledgements.markdown │ │ ├── Pods-acknowledgements.plist │ │ └── Pods-resources.sh │ └── Pods-TheAmazingAudioEngine │ │ ├── Pods-TheAmazingAudioEngine.xcconfig │ │ ├── Pods-TheAmazingAudioEngine-prefix.pch │ │ ├── Pods-TheAmazingAudioEngine-dummy.m │ │ └── Pods-TheAmazingAudioEngine-Private.xcconfig ├── Manifest.lock └── TheAmazingAudioEngine │ ├── License.txt │ ├── Modules │ ├── AEPlaythroughChannel.h │ ├── AELimiterFilter.h │ ├── AEExpanderFilter.h │ ├── AERecorder.h │ ├── AELimiterFilter.m │ ├── AERecorder.m │ ├── AEPlaythroughChannel.m │ └── AELimiter.h │ ├── TheAmazingAudioEngine │ ├── AEBlockAudioReceiver.h │ ├── AEBlockAudioReceiver.m │ ├── AEBlockChannel.m │ ├── AEBlockFilter.m │ ├── AEAudioController+AudiobusStub.h │ ├── AEAudioController+Audiobus.m │ ├── AEBlockChannel.h │ ├── AEBlockFilter.h │ ├── AEAudioFilePlayer.h │ ├── AEAudioUnitChannel.h │ ├── AEAudioController+Audiobus.h │ ├── AEAudioFileWriter.h │ ├── AEAudioFileLoaderOperation.h │ ├── AEAudioUnitFilter.h │ ├── AEUtilities.h │ ├── AEFloatConverter.h │ ├── AEUtilities.c │ ├── Library │ │ └── TPCircularBuffer │ │ │ ├── TPCircularBuffer.c │ │ │ └── TPCircularBuffer.h │ ├── AEBlockScheduler.h │ ├── AEAudioFilePlayer.m │ ├── AEAudioUnitChannel.m │ └── AEBlockScheduler.m │ └── README.markdown ├── Podfile.lock ├── AmazingSequencer.xcodeproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── AmazingSequencer.xcworkspace └── contents.xcworkspacedata ├── ElaborateDemoVC.h ├── README.md └── ElaborateDemoVC.m /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | pod 'TheAmazingAudioEngine' -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.xcuserdatad 3 | /build/ 4 | *.xccheckout -------------------------------------------------------------------------------- /Sounds/crick.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielelkin/Sequencer/HEAD/Sounds/crick.caf -------------------------------------------------------------------------------- /Sounds/hihat.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielelkin/Sequencer/HEAD/Sounds/hihat.caf -------------------------------------------------------------------------------- /Sounds/kick.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielelkin/Sequencer/HEAD/Sounds/kick.caf -------------------------------------------------------------------------------- /AmazingSequencer/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Sounds/woodblock.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielelkin/Sequencer/HEAD/Sounds/woodblock.caf -------------------------------------------------------------------------------- /AmazingSequencerTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AELimiter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AELimiter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AELimiter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AELimiter.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AERecorder.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AERecorder.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AERecorder.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AERecorder.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEMixerBuffer.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AEMixerBuffer.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEMixerBuffer.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AEMixerBuffer.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEExpanderFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AEExpanderFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AELimiterFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AELimiterFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEExpanderFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AEExpanderFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AELimiterFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AELimiterFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEUtilities.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEUtilities.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEUtilities.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEUtilities.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEBlockChannel.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEBlockFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEPlaythroughChannel.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AEPlaythroughChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEBlockChannel.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEBlockFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEPlaythroughChannel.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/Modules/AEPlaythroughChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioController.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioFilePlayer.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFilePlayer.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioFileWriter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFileWriter.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioUnitFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioUnitFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEBlockScheduler.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockScheduler.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEFloatConverter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEFloatConverter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioController.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioFilePlayer.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFilePlayer.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioFileWriter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFileWriter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioUnitFilter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioUnitFilter.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEBlockScheduler.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockScheduler.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEFloatConverter.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEFloatConverter.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioUnitChannel.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioUnitChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEBlockAudioReceiver.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockAudioReceiver.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioUnitChannel.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioUnitChannel.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/TheAmazingAudioEngine.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/TheAmazingAudioEngine.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEBlockAudioReceiver.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockAudioReceiver.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/TheAmazingAudioEngine.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/TheAmazingAudioEngine.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioController+Audiobus.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController+Audiobus.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioFileLoaderOperation.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFileLoaderOperation.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioController+Audiobus.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController+Audiobus.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioFileLoaderOperation.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFileLoaderOperation.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/AEAudioController+AudiobusStub.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController+AudiobusStub.h -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/TPCircularBuffer.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/Library/TPCircularBuffer/TPCircularBuffer.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/TPCircularBuffer.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/Library/TPCircularBuffer/TPCircularBuffer.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/AEAudioController+AudiobusStub.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController+AudiobusStub.h -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TheAmazingAudioEngine/Pods-TheAmazingAudioEngine.xcconfig: -------------------------------------------------------------------------------- 1 | PODS_THEAMAZINGAUDIOENGINE_OTHER_LDFLAGS = -framework "Accelerate" -framework "AudioToolbox" -------------------------------------------------------------------------------- /Pods/Headers/Build/TheAmazingAudioEngine/TPCircularBuffer+AudioBufferList.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/Library/TPCircularBuffer/TPCircularBuffer+AudioBufferList.h -------------------------------------------------------------------------------- /Pods/Headers/Public/TheAmazingAudioEngine/TPCircularBuffer+AudioBufferList.h: -------------------------------------------------------------------------------- 1 | ../../../TheAmazingAudioEngine/TheAmazingAudioEngine/Library/TPCircularBuffer/TPCircularBuffer+AudioBufferList.h -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TheAmazingAudioEngine/Pods-TheAmazingAudioEngine-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-environment.h" 6 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - TheAmazingAudioEngine (1.4.6) 3 | 4 | DEPENDENCIES: 5 | - TheAmazingAudioEngine 6 | 7 | SPEC CHECKSUMS: 8 | TheAmazingAudioEngine: 014e942f20456feaf5ccb48f440402306350abf8 9 | 10 | COCOAPODS: 0.35.0 11 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - TheAmazingAudioEngine (1.4.6) 3 | 4 | DEPENDENCIES: 5 | - TheAmazingAudioEngine 6 | 7 | SPEC CHECKSUMS: 8 | TheAmazingAudioEngine: 014e942f20456feaf5ccb48f440402306350abf8 9 | 10 | COCOAPODS: 0.35.0 11 | -------------------------------------------------------------------------------- /AmazingSequencer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TheAmazingAudioEngine/Pods-TheAmazingAudioEngine-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_TheAmazingAudioEngine : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_TheAmazingAudioEngine 5 | @end 6 | -------------------------------------------------------------------------------- /AmazingSequencer/WelcomeVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // WelcomeVC.h 3 | // AmazingSequencer 4 | // 5 | // Created by Ariel Elkin on 07/04/2015. 6 | // Copyright (c) 2015 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WelcomeVC : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AmazingSequencer/SimpleDemoVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleDemoVC.h 3 | // AmazingSequencer 4 | // 5 | // Created by Ariel Elkin on 07/04/2015. 6 | // Copyright (c) 2015 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SimpleDemoVC : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AmazingSequencer.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AmazingSequencer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 26/03/2014. 6 | // Copyright (c) 2014 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AmazingSequencer/AmazingSequencer-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /AmazingSequencer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 26/03/2014. 6 | // Copyright (c) 2014 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-TheAmazingAudioEngine/Pods-TheAmazingAudioEngine-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-TheAmazingAudioEngine.xcconfig" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/TheAmazingAudioEngine" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/TheAmazingAudioEngine" 4 | OTHER_LDFLAGS = ${PODS_THEAMAZINGAUDIOENGINE_OTHER_LDFLAGS} -ObjC 5 | PODS_ROOT = ${SRCROOT} -------------------------------------------------------------------------------- /AmazingSequencer/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/TheAmazingAudioEngine" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/TheAmazingAudioEngine" 4 | OTHER_LDFLAGS = -ObjC -l"Pods-TheAmazingAudioEngine" -framework "Accelerate" -framework "AudioToolbox" 5 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 6 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/TheAmazingAudioEngine" 3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/TheAmazingAudioEngine" 4 | OTHER_LDFLAGS = -ObjC -l"Pods-TheAmazingAudioEngine" -framework "Accelerate" -framework "AudioToolbox" 5 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 6 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-environment.h: -------------------------------------------------------------------------------- 1 | 2 | // To check if a library is compiled with CocoaPods you 3 | // can use the `COCOAPODS` macro definition which is 4 | // defined in the xcconfigs so it is available in 5 | // headers also when they are imported in the client 6 | // project. 7 | 8 | 9 | // TheAmazingAudioEngine 10 | #define COCOAPODS_POD_AVAILABLE_TheAmazingAudioEngine 11 | #define COCOAPODS_VERSION_MAJOR_TheAmazingAudioEngine 1 12 | #define COCOAPODS_VERSION_MINOR_TheAmazingAudioEngine 4 13 | #define COCOAPODS_VERSION_PATCH_TheAmazingAudioEngine 6 14 | 15 | -------------------------------------------------------------------------------- /AmazingSequencer/SequencerButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SequencerButton.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 16/03/2015. 6 | // 7 | 8 | #import 9 | 10 | @protocol SequencerButtonDelegate 11 | - (void)tappedButton:(id)button; 12 | @end 13 | 14 | @interface SequencerButton : UIView 15 | 16 | +(instancetype)buttonWithRow:(NSUInteger)row column:(NSUInteger)column; 17 | 18 | @property id delegate; 19 | 20 | @property NSUInteger row; 21 | @property NSUInteger column; 22 | @property BOOL isActive; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ElaborateDemoVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // ElaborateDemoVC.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 01/04/2014. 6 | // Copyright (c) 2014 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ElaborateDemoVC : UIViewController 12 | @property (strong, nonatomic) IBOutlet UISlider *mainVolumeSlider; 13 | @property (strong, nonatomic) IBOutlet UISlider *bpmSlider; 14 | @property (strong, nonatomic) IBOutlet UILabel *bpmLabel; 15 | @property (strong, nonatomic) IBOutlet UIProgressView *playheadPositionOfKickSequence; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /AmazingSequencer/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AmazingSequencer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 26/03/2014. 6 | // Copyright (c) 2014 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "WelcomeVC.h" 11 | 12 | @implementation AppDelegate 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 15 | { 16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 17 | self.window.backgroundColor = [UIColor whiteColor]; 18 | [self.window makeKeyAndVisible]; 19 | 20 | WelcomeVC *vc = [WelcomeVC new]; 21 | [self.window setRootViewController:vc]; 22 | 23 | return YES; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /AmazingSequencerTests/AmazingSequencerTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ariel.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /AmazingSequencerTests/AmazingSequencerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // The Amazing Audio EngineTests.m 3 | // The Amazing Audio EngineTests 4 | // 5 | // Created by Ariel Elkin on 26/03/2014. 6 | // Copyright (c) 2014 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AmazingSequencerTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AmazingSequencerTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/License.txt: -------------------------------------------------------------------------------- 1 | License 2 | 3 | Copyright (C) 2012-2013 A Tasty Pixel 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and must not be 19 | misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source distribution. 22 | -------------------------------------------------------------------------------- /AmazingSequencer/SequencerButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // SequencerButton.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 16/03/2015. 6 | // 7 | 8 | #import "SequencerButton.h" 9 | 10 | @implementation SequencerButton 11 | 12 | + (instancetype)buttonWithRow:(NSUInteger)row column:(NSUInteger)column { 13 | SequencerButton *sequencerButton = [[self alloc] init]; 14 | sequencerButton.row = row; 15 | sequencerButton.column = column; 16 | return sequencerButton; 17 | } 18 | 19 | - (id)init { 20 | self = [super init]; 21 | if (self) { 22 | self.backgroundColor = [UIColor whiteColor]; 23 | self.layer.borderColor = [UIColor blackColor].CGColor; 24 | self.layer.borderWidth = 3; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 30 | 31 | self.isActive = !self.isActive; 32 | 33 | if (self.isActive) { 34 | self.backgroundColor = [UIColor orangeColor]; 35 | } 36 | else { 37 | self.backgroundColor = [UIColor whiteColor]; 38 | } 39 | 40 | [self.delegate tappedButton:self]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /AmazingSequencer/AESequencerChannel.h: -------------------------------------------------------------------------------- 1 | // 2 | // AESequencerChannel.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Alejandro Santander on 26/02/2015. 6 | // 7 | 8 | #import 9 | #import "AEAudioController.h" 10 | #import "AESequencerBeat.h" 11 | #import "AESequencerChannelSequence.h" 12 | 13 | @interface AESequencerChannel : NSObject 14 | 15 | + (instancetype)sequencerChannelWithAudioFileAt:(NSURL *)url 16 | audioController:(AEAudioController*)audioController 17 | withSequence:(AESequencerChannelSequence*)sequence 18 | numberOfFullBeatsPerMeasure:(NSUInteger)beatsPerMeasure 19 | atBPM:(double)bpm; 20 | 21 | @property (nonatomic) AESequencerChannelSequence *sequence; 22 | @property (nonatomic, readwrite) float volume; 23 | @property (nonatomic, readwrite) float pan; 24 | @property bool sequenceIsPlaying; 25 | @property double bpm; 26 | @property (nonatomic, readonly) float playheadPosition; 27 | @property bool muted; 28 | @property int soloed; // 1 = soloed, -1 = not soloed, 0 = ignore 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## TheAmazingAudioEngine 5 | 6 | License 7 | 8 | Copyright (C) 2012-2013 A Tasty Pixel 9 | 10 | This software is provided 'as-is', without any express or implied 11 | warranty. In no event will the authors be held liable for any damages 12 | arising from the use of this software. 13 | 14 | Permission is granted to anyone to use this software for any purpose, 15 | including commercial applications, and to alter it and redistribute it 16 | freely, subject to the following restrictions: 17 | 18 | 1. The origin of this software must not be misrepresented; you must not 19 | claim that you wrote the original software. If you use this software 20 | in a product, an acknowledgment in the product documentation would be 21 | appreciated but is not required. 22 | 23 | 2. Altered source versions must be plainly marked as such, and must not be 24 | misrepresented as being the original software. 25 | 26 | 3. This notice may not be removed or altered from any source distribution. 27 | 28 | Generated by CocoaPods - http://cocoapods.org 29 | -------------------------------------------------------------------------------- /AmazingSequencer/AmazingSequencer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | ariel.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationLandscapeLeft 34 | UIInterfaceOrientationLandscapeRight 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /AmazingSequencer/AESequencerBeat.m: -------------------------------------------------------------------------------- 1 | // 2 | // AESequencerBeat.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 24/02/2015. 6 | // 7 | 8 | #import "AESequencerBeat.h" 9 | 10 | @implementation AESequencerBeat 11 | 12 | + (instancetype)beatWithOnset:(float)onset 13 | velocity:(float)velocity { 14 | 15 | AESequencerBeat *beat = [[self alloc] init]; 16 | beat.onset = onset; 17 | beat.velocity = velocity; 18 | return beat; 19 | } 20 | 21 | - (void)setOnset:(float)onset { 22 | if (onset >= 0) { 23 | _onset = onset; 24 | } 25 | else { 26 | NSLog(@"%s onset can't be < 0, setting to 0", __PRETTY_FUNCTION__); 27 | _onset = 0; 28 | } 29 | } 30 | 31 | - (void)setVelocity:(float)velocity { 32 | if(velocity >= 0 && velocity <= 1) { 33 | _velocity = velocity; 34 | } 35 | else if (velocity < 0) { 36 | NSLog(@"%s velocity can't be < 0, setting to 0", __PRETTY_FUNCTION__); 37 | _velocity = 0; 38 | } 39 | else if (velocity > 1) { 40 | NSLog(@"%s velocity can't be > 1, setting to 1", __PRETTY_FUNCTION__); 41 | _velocity = 1; 42 | } 43 | } 44 | 45 | + (instancetype)beatWithOnset:(float)onset { 46 | return [self beatWithOnset:onset velocity:1.0]; 47 | } 48 | 49 | - (NSString *)description { 50 | return [NSString stringWithFormat:@"Onset: %.3f ||| Velocity: %.3f", self.onset, self.velocity]; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /AmazingSequencer/AESequencerBeat.h: -------------------------------------------------------------------------------- 1 | // 2 | // AESequencerBeat.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 24/02/2015. 6 | // 7 | 8 | #import 9 | 10 | @interface AESequencerBeat : NSObject 11 | 12 | /*! 13 | * Initializes and returns an individual SequencerBeat 14 | * with a specified onset and a velocity. 15 | * 16 | */ 17 | + (instancetype)beatWithOnset:(float)onset 18 | velocity:(float)velocity; 19 | 20 | 21 | /*! 22 | * Initializes and returns an individual SequencerBeat 23 | * with a specified onset and velocity 1. 24 | * 25 | */ 26 | + (instancetype)beatWithOnset:(float)onset; 27 | 28 | 29 | /*! 30 | * The onset of the beat in relation to the sequence. 31 | * 32 | * @discussion Must be between 0 and 1. A value of 0 means the beat will 33 | * sound at the very beginning of the sequence, a value of 1 means 34 | * it will sound at the very end of it. 35 | * 36 | */ 37 | @property (nonatomic) float onset; 38 | 39 | /*! 40 | * The velocity of the beat. 41 | * 42 | * @discussion Must be between 0 and 1. A value of 0 means the beat will 43 | * be silent, a value of 1 means the beat will play at its 44 | * normal volume. 45 | * 46 | */ 47 | @property (nonatomic) float velocity; 48 | 49 | 50 | /*! 51 | * A struct that represents an individual beat. 52 | * 53 | */ 54 | typedef struct SequencerBeatCRepresentation { 55 | float onset; 56 | float velocity; 57 | } BEAT; 58 | 59 | @end -------------------------------------------------------------------------------- /AmazingSequencer/AESequencerChannelSequence.h: -------------------------------------------------------------------------------- 1 | // 2 | // AESequencerChannelSequence.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 03/03/2015. 6 | // 7 | 8 | #import 9 | #import "AESequencerBeat.h" 10 | 11 | @interface AESequencerChannelSequence : NSObject 12 | 13 | 14 | /*! 15 | * Adds a beat to the sequence. 16 | * 17 | * Beats are automatically sorted by their onsets, in 18 | * ascending order. 19 | * 20 | */ 21 | - (void)addBeat:(AESequencerBeat *)beat; 22 | 23 | 24 | /*! 25 | * Removes a beat from the sequence. 26 | * 27 | * Returns nil if sequence does not contain a beat 28 | * with specified onset. 29 | * 30 | */ 31 | - (void)removeBeatAtOnset:(float)onset; 32 | 33 | 34 | /*! 35 | * Sets the onset of a beat located at a specified onset 36 | * in the sequence. 37 | * 38 | */ 39 | - (void)setOnsetOfBeatAtOnset:(float)oldOnset to:(float)newOnset; 40 | 41 | 42 | /*! 43 | * Sets the velocity of a beat located at a specified onset 44 | * of the sequence. 45 | * 46 | */ 47 | - (void)setVelocityOfBeatAtOnset:(float)onset to:(float)newVelocity; 48 | 49 | 50 | /*! 51 | * Returns the beat with the specified onset in the sequence. 52 | * 53 | */ 54 | - (AESequencerBeat *)beatAtOnset:(float)onset; 55 | 56 | 57 | /* 58 | * Returns an array with all the beats in the sequence. 59 | * 60 | */ 61 | - (NSArray *)allBeats; 62 | 63 | 64 | /*! 65 | * Returns the number of beats present in the sequence. 66 | * 67 | */ 68 | @property (nonatomic, readonly) NSUInteger count; 69 | 70 | 71 | /*! 72 | * Returns a C representation of the sequence as an 73 | * array of BEAT. 74 | * 75 | */ 76 | @property (readonly) BEAT *sequenceCRepresentation; 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AEPlaythroughChannel.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEPlaythroughChannel.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 21/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | /*! 34 | * Playthrough channel, used for live monitoring of input 35 | */ 36 | @interface AEPlaythroughChannel : NSObject 37 | 38 | /*! 39 | * Initialise 40 | * 41 | * @param audioController The Audio Controller 42 | */ 43 | - (id)initWithAudioController:(AEAudioController*)audioController; 44 | 45 | @property (nonatomic, assign) float volume; 46 | @property (nonatomic, assign) float pan; 47 | @property (nonatomic, assign) BOOL channelIsMuted; 48 | @property (nonatomic, readonly) AudioStreamBasicDescription audioDescription; 49 | @end 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AELimiterFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AELimiterFilter.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 21/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | /*! 34 | * A wrapper around the @link AELimiter @endlink class that allows it 35 | * to be used as an AEAudioFilter. 36 | * 37 | * See the AELimiter documentation for descriptions of the parameters. 38 | */ 39 | @interface AELimiterFilter : NSObject 40 | 41 | /*! 42 | * Initialise 43 | * 44 | * @param audioController The Audio Controller 45 | */ 46 | - (id)initWithAudioController:(AEAudioController*)audioController; 47 | 48 | @property (nonatomic, assign) UInt32 hold; 49 | @property (nonatomic, assign) UInt32 attack; 50 | @property (nonatomic, assign) UInt32 decay; 51 | @property (nonatomic, assign) float level; 52 | 53 | @property (nonatomic, assign) AudioStreamBasicDescription clientFormat; 54 | @end 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockAudioReceiver.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockAudioReceiver.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 21/02/2013. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | typedef void (^AEBlockAudioReceiverBlock)(void *source, 34 | const AudioTimeStamp *time, 35 | UInt32 frames, 36 | AudioBufferList *audio); 37 | 38 | /*! 39 | * Block audio receiver: Utility class to allow use of a block to receive audio 40 | */ 41 | @interface AEBlockAudioReceiver : NSObject 42 | 43 | /*! 44 | * Create a new audio receiver with a given block 45 | * 46 | * @param block Block to use for audio generation 47 | */ 48 | + (AEBlockAudioReceiver*)audioReceiverWithBlock:(AEBlockAudioReceiverBlock)block; 49 | 50 | @end 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | License 18 | 19 | Copyright (C) 2012-2013 A Tasty Pixel 20 | 21 | This software is provided 'as-is', without any express or implied 22 | warranty. In no event will the authors be held liable for any damages 23 | arising from the use of this software. 24 | 25 | Permission is granted to anyone to use this software for any purpose, 26 | including commercial applications, and to alter it and redistribute it 27 | freely, subject to the following restrictions: 28 | 29 | 1. The origin of this software must not be misrepresented; you must not 30 | claim that you wrote the original software. If you use this software 31 | in a product, an acknowledgment in the product documentation would be 32 | appreciated but is not required. 33 | 34 | 2. Altered source versions must be plainly marked as such, and must not be 35 | misrepresented as being the original software. 36 | 37 | 3. This notice may not be removed or altered from any source distribution. 38 | 39 | Title 40 | TheAmazingAudioEngine 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - http://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sequencer 2 | Example use of the sequencer plugin for [The Amazing Audio Engine](https://github.com/TheAmazingAudioEngine/TheAmazingAudioEngine). 3 | 4 | See [SwiftySequencer](https://github.com/arielelkin/SwiftySequencer) for a Swift implementation. 5 | 6 | ##Use 7 | Clone this repository, add `pod 'TheAmazingAudioEngine'` to your pod file or [manually add The Amazing Audio Engine](http://theamazingaudioengine.com/doc/_getting-_started.html). 8 | 9 | In this example we will play a sound every [quarter note](http://en.wikipedia.org/wiki/Quarter_note): 10 | 11 | //Add an audio file to your Xcode project and get its `NSURL` : 12 | NSURL *woodblockSoundURL = [[NSBundle mainBundle] URLForResource:@"woodblock" withExtension:@"caf"]; 13 | 14 | //Next, specify when the sound should play in relation to the whole sequence, 15 | //by adding instances of AESequencerBeat to your AESequencerChannelSequence. 16 | //The onset property of an AESequencerBeat should be between 0 and 1. 17 | AESequencerChannelSequence *woodblockSoundSequence = [AESequencerChannelSequence new]; 18 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0]]; 19 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0.25]]; 20 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0.50]]; 21 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0.75]]; 22 | 23 | //Then, create a AESequencerChannel that will play the sequence: 24 | woodBlockSoundChannel = [AESequencerChannel sequencerChannelWithAudioFileAt:woodblockSoundURL 25 | audioController:audioController 26 | withSequence:woodblockSoundSequence 27 | numberOfFullBeatsPerMeasure:4 28 | atBPM:120]; 29 | 30 | //Add the channel to the `AEAudioController`: 31 | [audioController addChannels:@[woodBlockSoundChannel]]; 32 | 33 | //Tell it to start playing: 34 | woodBlockSoundChannel.sequenceIsPlaying = true; 35 | 36 | Happy sequencing! 37 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/README.markdown: -------------------------------------------------------------------------------- 1 | The Amazing Audio Engine 2 | ======================== 3 | 4 | The Amazing Audio Engine is a sophisticated framework for iOS audio applications, built so you don't have to. 5 | 6 | It is designed to be very easy to work with, and handles all of the intricacies of iOS audio on your behalf. 7 | 8 | Built upon the efficient and low-latency Core Audio Remote IO system, and written by one of the pioneers of iOS audio development and developer of [Audiobus](http://audiob.us) Michael Tyson, The Amazing Audio Engine lets you get to work on making your app great instead of reinventing the wheel. 9 | 10 | See http://theamazingaudioengine.com for details and http://theamazingaudioengine.com/doc for documentation. 11 | 12 | 13 |
14 |
by MacBuildServer 15 |
16 | 17 | License 18 | ------- 19 | 20 | Copyright (C) 2012-2013 A Tasty Pixel 21 | 22 | This software is provided 'as-is', without any express or implied 23 | warranty. In no event will the authors be held liable for any damages 24 | arising from the use of this software. 25 | 26 | Permission is granted to anyone to use this software for any purpose, 27 | including commercial applications, and to alter it and redistribute it 28 | freely, subject to the following restrictions: 29 | 30 | 1. The origin of this software must not be misrepresented; you must not 31 | claim that you wrote the original software. If you use this software 32 | in a product, an acknowledgment in the product documentation would be 33 | appreciated but is not required. 34 | 35 | 2. Altered source versions must be plainly marked as such, and must not be 36 | misrepresented as being the original software. 37 | 38 | 3. This notice may not be removed or altered from any source distribution. 39 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockAudioReceiver.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockAudioReceiver.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 21/02/2013. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AEBlockAudioReceiver.h" 27 | 28 | @interface AEBlockAudioReceiver () 29 | @property (nonatomic, copy) AEBlockAudioReceiverBlock block; 30 | @end 31 | 32 | @implementation AEBlockAudioReceiver 33 | @synthesize block = _block; 34 | 35 | - (id)initWithBlock:(AEBlockAudioReceiverBlock)block { 36 | if ( !(self = [super init]) ) self = nil; 37 | self.block = block; 38 | return self; 39 | } 40 | 41 | + (AEBlockAudioReceiver*)audioReceiverWithBlock:(AEBlockAudioReceiverBlock)block { 42 | return [[AEBlockAudioReceiver alloc] initWithBlock:block]; 43 | } 44 | 45 | 46 | static void receiverCallback(__unsafe_unretained AEBlockAudioReceiver *THIS, 47 | __unsafe_unretained AEAudioController *audioController, 48 | void *source, 49 | const AudioTimeStamp *time, 50 | UInt32 frames, 51 | AudioBufferList *audio) { 52 | THIS->_block(source, time, frames, audio); 53 | } 54 | 55 | -(AEAudioControllerAudioCallback)receiverCallback { 56 | return receiverCallback; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockChannel.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockChannel.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 20/12/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AEBlockChannel.h" 27 | 28 | @interface AEBlockChannel () 29 | @property (nonatomic, copy) AEBlockChannelBlock block; 30 | @end 31 | 32 | @implementation AEBlockChannel 33 | @synthesize block = _block; 34 | 35 | - (id)initWithBlock:(AEBlockChannelBlock)block { 36 | if ( !(self = [super init]) ) self = nil; 37 | self.volume = 1.0; 38 | self.pan = 0.0; 39 | self.block = block; 40 | self.channelIsMuted = NO; 41 | self.channelIsPlaying = YES; 42 | return self; 43 | } 44 | 45 | + (AEBlockChannel*)channelWithBlock:(AEBlockChannelBlock)block { 46 | return [[AEBlockChannel alloc] initWithBlock:block]; 47 | } 48 | 49 | 50 | static OSStatus renderCallback(__unsafe_unretained AEBlockChannel *THIS, 51 | __unsafe_unretained AEAudioController *audioController, 52 | const AudioTimeStamp *time, 53 | UInt32 frames, 54 | AudioBufferList *audio) { 55 | THIS->_block(time, frames, audio); 56 | return noErr; 57 | } 58 | 59 | -(AEAudioControllerRenderCallback)renderCallback { 60 | return renderCallback; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockFilter.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 20/12/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AEBlockFilter.h" 27 | 28 | @interface AEBlockFilter () 29 | @property (nonatomic, copy) AEBlockFilterBlock block; 30 | @end 31 | 32 | @implementation AEBlockFilter 33 | @synthesize block = _block; 34 | 35 | - (id)initWithBlock:(AEBlockFilterBlock)block { 36 | if ( !(self = [super init]) ) self = nil; 37 | self.block = block; 38 | return self; 39 | } 40 | 41 | + (AEBlockFilter*)filterWithBlock:(AEBlockFilterBlock)block { 42 | return [[AEBlockFilter alloc] initWithBlock:block]; 43 | } 44 | 45 | 46 | static OSStatus filterCallback(__unsafe_unretained AEBlockFilter *THIS, 47 | __unsafe_unretained AEAudioController *audioController, 48 | AEAudioControllerFilterProducer producer, 49 | void *producerToken, 50 | const AudioTimeStamp *time, 51 | UInt32 frames, 52 | AudioBufferList *audio) { 53 | THIS->_block(producer, producerToken, time, frames, audio); 54 | return noErr; 55 | } 56 | 57 | -(AEAudioControllerFilterCallback)filterCallback { 58 | return filterCallback; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController+AudiobusStub.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioController+AudiobusStub.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 07/05/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import 27 | 28 | @class ABReceiverPort; 29 | @class ABSenderPort; 30 | @class ABFilterPort; 31 | @class ABPort; 32 | 33 | extern NSString * const ABConnectionsChangedNotification; 34 | 35 | void ABReceiverPortReceive(ABReceiverPort *receiverPort, ABPort *sourcePortOrNil, AudioBufferList *bufferList, UInt32 lengthInFrames, AudioTimeStamp *outTimestamp); 36 | BOOL ABReceiverPortIsConnected(ABReceiverPort *receiverPort); 37 | BOOL ABFilterPortIsConnected(ABFilterPort *filterPort); 38 | void ABSenderPortSend(ABSenderPort* senderPort, const AudioBufferList *audio, UInt32 lengthInFrames, const AudioTimeStamp *timestamp); 39 | BOOL ABSenderPortIsConnected(ABSenderPort *senderPort); 40 | BOOL ABSenderPortIsMuted(ABSenderPort *senderPort); 41 | NSTimeInterval ABSenderPortGetAverageLatency(ABSenderPort *senderPort); 42 | typedef void (^ABReceiverPortAudioInputBlock)(ABReceiverPort *receiverPort, UInt32 lengthInFrames, AudioTimeStamp nextTimestamp, ABPort *sourcePortOrNil); 43 | 44 | @protocol AEAudiobusForwardDeclarationsProtocol 45 | - (AudioStreamBasicDescription)clientFormat; 46 | - (void)setClientFormat:(AudioStreamBasicDescription)clientFormat; 47 | - (BOOL)connectedToSelf; 48 | - (void)setAutomaticMonitoring:(BOOL)automaticMonitoring; 49 | - (AudioUnit)audioUnit; 50 | - (BOOL)connected; 51 | @end 52 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController+Audiobus.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioController+Audiobus.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 07/05/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AEAudioController+Audiobus.h" 27 | #import "AEAudioController+AudiobusStub.h" 28 | 29 | __attribute__((weak)) void ABReceiverPortReceive(ABReceiverPort *receiverPort, ABPort *sourcePortOrNil, AudioBufferList *bufferList, UInt32 lengthInFrames, AudioTimeStamp *outTimestamp) { 30 | printf("ABReceiverPortReceive stub called\n"); 31 | } 32 | 33 | __attribute__((weak)) BOOL ABReceiverPortIsConnected(ABReceiverPort *receiverPort) { 34 | printf("ABReceiverPortIsConnected stub called\n"); 35 | return NO; 36 | } 37 | 38 | __attribute__((weak)) BOOL ABFilterPortIsConnected(ABFilterPort *filterPort) { 39 | printf("ABFilterPortIsConnected stub called\n"); 40 | return NO; 41 | } 42 | 43 | __attribute__((weak)) void ABSenderPortSend(ABSenderPort* senderPort, const AudioBufferList *audio, UInt32 lengthInFrames, const AudioTimeStamp *timestamp) { 44 | printf("ABSenderPortSend stub called\n"); 45 | } 46 | 47 | __attribute__((weak)) BOOL ABSenderPortIsConnected(ABSenderPort *senderPort) { 48 | printf("ABSenderPortIsConnected stub called\n"); 49 | return NO; 50 | } 51 | 52 | __attribute__((weak)) BOOL ABSenderPortIsMuted(ABSenderPort *senderPort) { 53 | printf("ABSenderPortIsMuted stub called\n"); 54 | return NO; 55 | } 56 | 57 | __attribute__((weak)) NSTimeInterval ABSenderPortGetAverageLatency(ABSenderPort *senderPort) { 58 | printf("ABSenderPortGetAverageLatency stub called\n"); 59 | return 0; 60 | } 61 | 62 | __attribute__((weak)) NSString * const ABConnectionsChangedNotification = @"ABConnectionsChangedNotification"; 63 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockChannel.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockChannel.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 20/12/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | typedef void (^AEBlockChannelBlock)(const AudioTimeStamp *time, 34 | UInt32 frames, 35 | AudioBufferList *audio); 36 | 37 | /*! 38 | * Block channel: Utility class to allow use of a block to generate audio 39 | */ 40 | @interface AEBlockChannel : NSObject 41 | 42 | /*! 43 | * Create a new channel with a given block 44 | * 45 | * @param block Block to use for audio generation 46 | */ 47 | + (AEBlockChannel*)channelWithBlock:(AEBlockChannelBlock)block; 48 | 49 | /*! 50 | * Track volume 51 | * 52 | * Range: 0.0 to 1.0 53 | */ 54 | @property (nonatomic, assign) float volume; 55 | 56 | /*! 57 | * Track pan 58 | * 59 | * Range: -1.0 (left) to 1.0 (right) 60 | */ 61 | @property (nonatomic, assign) float pan; 62 | 63 | /* 64 | * Whether channel is currently playing 65 | * 66 | * If this is NO, then the track will be silenced and no further render callbacks 67 | * will be performed until set to YES again. 68 | */ 69 | @property (nonatomic, assign) BOOL channelIsPlaying; 70 | 71 | /* 72 | * Whether channel is muted 73 | * 74 | * If YES, track will be silenced, but render callbacks will continue to be performed. 75 | */ 76 | @property (nonatomic, assign) BOOL channelIsMuted; 77 | 78 | /* 79 | * The audio format for this channel 80 | */ 81 | @property (nonatomic, assign) AudioStreamBasicDescription audioDescription; 82 | 83 | @end 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif -------------------------------------------------------------------------------- /AmazingSequencer/AESequencerChannelSequence.m: -------------------------------------------------------------------------------- 1 | // 2 | // AESequencerChannelSequence.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 03/03/2015. 6 | // 7 | 8 | #import "AESequencerChannelSequence.h" 9 | 10 | 11 | @implementation AESequencerChannelSequence { 12 | NSMutableArray *sequence; 13 | BEAT* _sequenceCRepresentation; 14 | } 15 | 16 | - (void)addBeat:(AESequencerBeat *)beat { 17 | 18 | if (!beat) return; 19 | 20 | if (!sequence) { 21 | sequence = [NSMutableArray array]; 22 | } 23 | 24 | [sequence addObject:beat]; 25 | 26 | [sequence sortUsingComparator:^NSComparisonResult(AESequencerBeat *beat1, AESequencerBeat *beat2) { 27 | return beat1.onset > beat2.onset; 28 | }]; 29 | 30 | 31 | [self updateSequenceCRepresentation]; 32 | } 33 | 34 | - (void)removeBeatAtOnset:(float)onset { 35 | for (int i = 0; i < sequence.count; i++) { 36 | AESequencerBeat *beat = sequence[i]; 37 | if (beat.onset == onset) { 38 | [sequence removeObject:beat]; 39 | } 40 | } 41 | 42 | [self updateSequenceCRepresentation]; 43 | } 44 | 45 | - (void)setOnsetOfBeatAtOnset:(float)oldOnset to:(float)newOnset { 46 | AESequencerBeat *beat = [self beatAtOnset:oldOnset]; 47 | beat.onset = newOnset; 48 | } 49 | 50 | - (void)setVelocityOfBeatAtOnset:(float)onset to:(float)newVelocity { 51 | AESequencerBeat *beat = [self beatAtOnset:onset]; 52 | beat.velocity = newVelocity; 53 | } 54 | 55 | - (AESequencerBeat *)beatAtOnset:(float)onset { 56 | 57 | for (AESequencerBeat *beat in sequence) { 58 | if (beat.onset == onset) { 59 | return beat; 60 | } 61 | } 62 | return nil; 63 | } 64 | 65 | - (NSArray *)allBeats { 66 | return [NSArray arrayWithArray:sequence]; 67 | } 68 | 69 | - (NSUInteger)count { 70 | return sequence.count; 71 | } 72 | 73 | #pragma mark - 74 | #pragma mark C Representation 75 | 76 | - (void)updateSequenceCRepresentation { 77 | NSUInteger numberOfBeats = sequence.count; 78 | 79 | _sequenceCRepresentation = (BEAT *)malloc(sizeof(BEAT) * numberOfBeats); 80 | 81 | // NSLog(@"sequence: "); 82 | 83 | for(int i=0; i < numberOfBeats; i++) { 84 | 85 | AESequencerBeat *beat = sequence[i]; 86 | 87 | BEAT cBeat; 88 | cBeat.onset = beat.onset; 89 | cBeat.velocity = beat.velocity; 90 | // NSLog(@" beat: %d of %d, %f", i, numberOfBeats, beat.onset); 91 | 92 | _sequenceCRepresentation[i] = cBeat; 93 | 94 | } 95 | } 96 | 97 | - (BEAT *)sequenceCRepresentation { 98 | return _sequenceCRepresentation; 99 | } 100 | 101 | 102 | #pragma mark - 103 | #pragma mark Description 104 | 105 | - (NSString *)description { 106 | NSMutableString *description = @"Sequence Description:\n".mutableCopy; 107 | 108 | for (AESequencerBeat *beat in sequence) { 109 | [description appendFormat:@"%@\n", beat.description]; 110 | } 111 | return description; 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockFilter.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 20/12/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | /*! 34 | * Filter processing block 35 | * 36 | * A filter implementation must call the function pointed to by the *producer* argument, 37 | * passing *producerToken*, *audio*, and *frames* as arguments, in order to produce as much 38 | * audio is required to produce *frames* frames of output audio: 39 | * 40 | * OSStatus status = producer(producerToken, audio, &frames); 41 | * if ( status != noErr ) return status; 42 | * 43 | * Then the audio can be processed as desired. 44 | * 45 | * @param producer A function to be called to produce audio for filtering 46 | * @param producerToken An opaque pointer to be passed to *producer* when producing audio 47 | * @param time The time the output audio will be played or the time input audio was received, automatically compensated for hardware latency. 48 | * @param frames The length of the required audio, in frames 49 | * @param audio The audio buffer list to write output audio to 50 | */ 51 | typedef void (^AEBlockFilterBlock)(AEAudioControllerFilterProducer producer, 52 | void *producerToken, 53 | const AudioTimeStamp *time, 54 | UInt32 frames, 55 | AudioBufferList *audio); 56 | 57 | /*! 58 | * Block filter: Utility class to allow use of a block to filter audio 59 | */ 60 | @interface AEBlockFilter : NSObject 61 | 62 | /*! 63 | * Create a new filter with a given block 64 | * 65 | * @param block Block to use for audio generation 66 | */ 67 | + (AEBlockFilter*)filterWithBlock:(AEBlockFilterBlock)block; 68 | 69 | /* 70 | * The audio format for this filter 71 | */ 72 | @property (nonatomic, assign) AudioStreamBasicDescription audioDescription; 73 | 74 | @end 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFilePlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioFilePlayer.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Michael Tyson on 13/02/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "AEAudioController.h" 32 | 33 | /*! 34 | * Audio file player 35 | * 36 | * This class allows you to play audio files, either as one-off samples, or looped. 37 | * It will play any audio file format supported by iOS. 38 | * 39 | * To use, create an instance, then add it to the audio controller. 40 | */ 41 | @interface AEAudioFilePlayer : NSObject 42 | 43 | /*! 44 | * Create a new player instance 45 | * 46 | * @param url URL to the file to load 47 | * @param audioController The audio controller 48 | * @param error If not NULL, the error on output 49 | * @return The audio player, ready to be @link AEAudioController::addChannels: added @endlink to the audio controller. 50 | */ 51 | + (id)audioFilePlayerWithURL:(NSURL*)url audioController:(AEAudioController*)audioController error:(NSError**)error; 52 | 53 | @property (nonatomic, strong, readonly) NSURL *url; //!< Original media URL 54 | @property (nonatomic, readonly) NSTimeInterval duration; //!< Length of audio, in seconds 55 | @property (nonatomic, assign) NSTimeInterval currentTime; //!< Current playback position, in seconds 56 | @property (nonatomic, readwrite) BOOL loop; //!< Whether to loop this track 57 | @property (nonatomic, readwrite) float volume; //!< Track volume 58 | @property (nonatomic, readwrite) float pan; //!< Track pan 59 | @property (nonatomic, readwrite) BOOL channelIsPlaying; //!< Whether the track is playing 60 | @property (nonatomic, readwrite) BOOL channelIsMuted; //!< Whether the track is muted 61 | @property (nonatomic, readwrite) BOOL removeUponFinish; //!< Whether the track automatically removes itself from the audio controller after playback completes 62 | @property (nonatomic, copy) void(^completionBlock)(); //!< A block to be called when playback finishes 63 | @property (nonatomic, copy) void(^startLoopBlock)(); //!< A block to be called when the loop restarts in loop mode 64 | @end 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AEExpanderFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEExpanderFilter.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Michael Tyson on 09/07/2011. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | #define AEExpanderFilterRatioGateMode 0 34 | 35 | /*! 36 | * @enum AEExpanderFilterPreset 37 | * Presets to use with the expander filter 38 | * 39 | * @var AEExpanderFilterPresetNone 40 | * No preset 41 | * @var AEExpanderFilterPresetSmooth 42 | * A smooth-sounding preset with a gentle ratio 43 | * @var AEExpanderFilterPresetMedium 44 | * A medium-level preset with 1/8 ratio and 5ms attack 45 | * @var AEExpanderFilterPresetPercussive 46 | * A gate-mode preset with 1ms attack, good for persussive audio 47 | */ 48 | typedef enum { 49 | AEExpanderFilterPresetNone=-1, 50 | AEExpanderFilterPresetSmooth=0, 51 | AEExpanderFilterPresetMedium=1, 52 | AEExpanderFilterPresetPercussive=2 53 | } AEExpanderFilterPreset; 54 | 55 | /*! 56 | * An expander/noise gate filter 57 | * 58 | * This class implements an expander filter, which reduces audio 59 | * levels beneath a set threshold in order to hide background noise. 60 | */ 61 | @interface AEExpanderFilter : NSObject 62 | 63 | /*! 64 | * Initialise 65 | * 66 | * @param audioController The Audio Controller 67 | */ 68 | - (id)initWithAudioController:(AEAudioController*)audioController; 69 | 70 | 71 | /*! 72 | * Apply a preset 73 | */ 74 | - (void)assignPreset:(AEExpanderFilterPreset)preset; 75 | 76 | /*! 77 | * Calibrate the threshold 78 | * 79 | * This method enters calibration mode, watching the input level 80 | * and setting the threshold to the maximum level seen. The user 81 | * should be silent during this period, to get an accurate measure 82 | * of the noise floor. 83 | * 84 | * @param block Block to perform when calibration is complete 85 | */ 86 | - (void)startCalibratingWithCompletionBlock:(void (^)(void))block; 87 | 88 | @property (nonatomic, assign) AudioStreamBasicDescription clientFormat; 89 | 90 | @property (nonatomic, assign) float ratio; 91 | @property (nonatomic, assign) double threshold; 92 | @property (nonatomic, assign) double hysteresis; 93 | @property (nonatomic, assign) NSTimeInterval attack; 94 | @property (nonatomic, assign) NSTimeInterval decay; 95 | 96 | @end 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif -------------------------------------------------------------------------------- /AmazingSequencer/WelcomeVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // WelcomeVC.m 3 | // AmazingSequencer 4 | // 5 | // Created by Ariel Elkin on 07/04/2015. 6 | // Copyright (c) 2015 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import "WelcomeVC.h" 10 | #import "SimpleDemoVC.h" 11 | #import "ElaborateDemoVC.h" 12 | 13 | @interface WelcomeVC() 14 | @end 15 | 16 | @implementation WelcomeVC 17 | 18 | - (void)viewDidLoad { 19 | 20 | UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 21 | tableView.delegate = self; 22 | tableView.dataSource = self; 23 | tableView.translatesAutoresizingMaskIntoConstraints = NO; 24 | [self.view addSubview:tableView]; 25 | 26 | NSArray *tableViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:@{@"tableView": tableView}]; 27 | [self.view addConstraints:tableViewConstraints]; 28 | 29 | tableViewConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[tableView]|" options:0 metrics:nil views:@{@"tableView": tableView}]; 30 | [self.view addConstraints:tableViewConstraints]; 31 | } 32 | 33 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 34 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 35 | if (indexPath.row == 0) { 36 | SimpleDemoVC *vc = [SimpleDemoVC new]; 37 | [self presentViewController:vc animated:YES completion:nil]; 38 | } 39 | 40 | else if (indexPath.row == 1) { 41 | ElaborateDemoVC *vc = [ElaborateDemoVC new]; 42 | [self presentViewController:vc animated:YES completion:nil]; 43 | } 44 | } 45 | 46 | 47 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 48 | return 2; 49 | } 50 | 51 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 52 | 53 | static NSString *cellIdentifier = @"cell"; 54 | UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 55 | if (!cell) { 56 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; 57 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 58 | } 59 | if (indexPath.row == 0) { 60 | cell.textLabel.text = @"Simple demo"; 61 | } 62 | 63 | else if (indexPath.row == 1) { 64 | cell.textLabel.text = @"Elaborate demo"; 65 | } 66 | 67 | return cell; 68 | } 69 | 70 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 71 | { 72 | 73 | static NSString *headerReuseIdentifier = @"TableViewSectionHeaderViewIdentifier"; 74 | 75 | UITableViewHeaderFooterView *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier]; 76 | if(sectionHeaderView == nil){ 77 | sectionHeaderView = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:headerReuseIdentifier]; 78 | } 79 | 80 | [sectionHeaderView.textLabel setTextColor:[UIColor colorWithRed:74/255.0 green:74/255.0 blue:74/255.0 alpha:1]]; 81 | [sectionHeaderView.textLabel setShadowColor:[UIColor whiteColor]]; 82 | [sectionHeaderView.textLabel setShadowOffset:CGSizeMake(0, 1)]; 83 | sectionHeaderView.textLabel.text = @"The Amazing Audio Engine - Sequencer Demo"; 84 | sectionHeaderView.textLabel.numberOfLines = 0; 85 | 86 | return sectionHeaderView; 87 | } 88 | 89 | -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 90 | return 100; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioUnitChannel.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioUnitChannel.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 01/02/2013. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | /*! 34 | * Audio Unit Channel 35 | * 36 | * This class allows you to add Audio Units as channels. Provide an 37 | * AudioComponentDescription that describes the audio unit, and the 38 | * corresponding audio unit will be initialised, ready for use 39 | * 40 | */ 41 | @interface AEAudioUnitChannel : NSObject 42 | 43 | /*! 44 | * Create a new Audio Unit channel 45 | * 46 | * @param audioComponentDescription The structure that identifies the audio unit 47 | * @param audioController The audio controller 48 | * @param error On output, if not NULL, will point to an error if a problem occurred 49 | * @return The initialised channel 50 | */ 51 | - (id)initWithComponentDescription:(AudioComponentDescription)audioComponentDescription 52 | audioController:(AEAudioController*)audioController 53 | error:(NSError**)error; 54 | 55 | /*! 56 | * Create a new Audio Unit channel, with a block to run before initialization of the unit 57 | * 58 | * @param audioComponentDescription The structure that identifies the audio unit 59 | * @param audioController The audio controller 60 | * @param preInitializeBlock A block to run before the audio unit is initialized. 61 | * This can be used to set some properties that needs to be set before the unit is initialized. 62 | * @param error On output, if not NULL, will point to an error if a problem occurred 63 | * @return The initialised channel 64 | */ 65 | - (id)initWithComponentDescription:(AudioComponentDescription)audioComponentDescription 66 | audioController:(AEAudioController*)audioController 67 | preInitializeBlock:(void(^)(AudioUnit audioUnit))block 68 | error:(NSError**)error; 69 | 70 | /*! 71 | * Track volume 72 | * 73 | * Range: 0.0 to 1.0 74 | */ 75 | @property (nonatomic, assign) float volume; 76 | 77 | /*! 78 | * Track pan 79 | * 80 | * Range: -1.0 (left) to 1.0 (right) 81 | */ 82 | @property (nonatomic, assign) float pan; 83 | 84 | /* 85 | * Whether channel is currently playing 86 | * 87 | * If this is NO, then the track will be silenced and no further render callbacks 88 | * will be performed until set to YES again. 89 | */ 90 | @property (nonatomic, assign) BOOL channelIsPlaying; 91 | 92 | /* 93 | * Whether channel is muted 94 | * 95 | * If YES, track will be silenced, but render callbacks will continue to be performed. 96 | */ 97 | @property (nonatomic, assign) BOOL channelIsMuted; 98 | 99 | /*! 100 | * The audio unit 101 | */ 102 | @property (nonatomic, readonly) AudioUnit audioUnit; 103 | 104 | /*! 105 | * The audio graph node 106 | */ 107 | @property (nonatomic, readonly) AUNode audioGraphNode; 108 | 109 | @end 110 | 111 | #ifdef __cplusplus 112 | } 113 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioController+Audiobus.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioController+Audiobus.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 06/05/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "AEAudioController.h" 32 | #import 33 | 34 | @class ABReceiverPort; 35 | @class ABSenderPort; 36 | @class ABFilterPort; 37 | 38 | @interface AEAudioController (AudiobusAdditions) 39 | 40 | /*! 41 | * Set an Audiobus sender port to send audio from a particular channel 42 | * 43 | * When assigned to a channel and connected via Audiobus, audio for the given channel 44 | * will be sent out the Audiobus sender port. 45 | * 46 | * @param senderPort The Audiobus sender port, or nil to remove the port 47 | * @param channel Channel for the sender port 48 | */ 49 | - (void)setAudiobusSenderPort:(ABSenderPort*)senderPort forChannel:(id)channel; 50 | 51 | /*! 52 | * Set an Audiobus sender port to send audio from a particular channel group 53 | * 54 | * When assigned to a channel and connected via Audiobus, audio for the given group 55 | * will be sent out the Audiobus sender port. 56 | * 57 | * @param senderPort The Audiobus sender port, or nil to remove the port 58 | * @param channelGroup Channel group for the sender port 59 | */ 60 | - (void)setAudiobusSenderPort:(ABSenderPort*)senderPort forChannelGroup:(AEChannelGroupRef)channelGroup; 61 | 62 | /*! 63 | * Audiobus receiver port 64 | * 65 | * Set this property to an Audiobus receiver port to receive audio 66 | * from this port instead of the system audio input. 67 | */ 68 | @property (nonatomic, retain) ABReceiverPort *audiobusReceiverPort; 69 | 70 | /*! 71 | * Audiobus filter port 72 | * 73 | * Set this property to an Audiobus filter port to let TAAE correctly update the 74 | * number of input channels when connected. 75 | */ 76 | @property (nonatomic, retain) ABFilterPort *audiobusFilterPort; 77 | 78 | /*! 79 | * Audiobus sender port 80 | * 81 | * Set this property to an Audiobus sender port to send system 82 | * output out this port. 83 | * 84 | * Generally speaking, it's more efficient to not use this property, and 85 | * instead use ABSenderPort's audio unit initializer (using 86 | * AEAudioController's [audioUnit](@ref AEAudioController::audioUnit) property. 87 | * 88 | * However, there are certain circumstances where it's preferable to 89 | * use the audiobusSenderPort property instead: Namely, where you are 90 | * using multiple ABSenderPorts, or where you intend to provide an 91 | * ABReceiverPort with the ability to connect to your own ABSenderPort 92 | * (ABAudiobusController's 'allowsConnectionsToSelf') for feeding your 93 | * input with your own output. These tricky cases require special 94 | * handling, which TAAE can do for you. 95 | * 96 | * Note that you cannot initialise ABSenderPort with TAAE's audio unit, 97 | * then use the sender port with this property. 98 | */ 99 | @property (nonatomic, retain) ABSenderPort *audiobusSenderPort; 100 | 101 | @end 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | install_resource() 10 | { 11 | case $1 in 12 | *.storyboard) 13 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 14 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 15 | ;; 16 | *.xib) 17 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 18 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 19 | ;; 20 | *.framework) 21 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 22 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 23 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 25 | ;; 26 | *.xcdatamodel) 27 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 28 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 29 | ;; 30 | *.xcdatamodeld) 31 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 32 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 33 | ;; 34 | *.xcmappingmodel) 35 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 36 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 37 | ;; 38 | *.xcassets) 39 | ;; 40 | /*) 41 | echo "$1" 42 | echo "$1" >> "$RESOURCES_TO_COPY" 43 | ;; 44 | *) 45 | echo "${PODS_ROOT}/$1" 46 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 47 | ;; 48 | esac 49 | } 50 | 51 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 52 | if [[ "${ACTION}" == "install" ]]; then 53 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 54 | fi 55 | rm -f "$RESOURCES_TO_COPY" 56 | 57 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ] 58 | then 59 | case "${TARGETED_DEVICE_FAMILY}" in 60 | 1,2) 61 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 62 | ;; 63 | 1) 64 | TARGET_DEVICE_ARGS="--target-device iphone" 65 | ;; 66 | 2) 67 | TARGET_DEVICE_ARGS="--target-device ipad" 68 | ;; 69 | *) 70 | TARGET_DEVICE_ARGS="--target-device mac" 71 | ;; 72 | esac 73 | find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 74 | fi 75 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFileWriter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioFileWriter.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Michael Tyson on 20/03/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import 32 | 33 | extern NSString * const AEAudioFileWriterErrorDomain; 34 | 35 | enum { 36 | kAEAudioFileWriterFormatError 37 | }; 38 | 39 | @class AEAudioController; 40 | 41 | /*! 42 | * Audio file writer 43 | * 44 | * Provides an easy-to-use interface to the ExtAudioFile API, allowing 45 | * asynchronous, Core Audio thread-safe writing of arbitrary audio formats. 46 | */ 47 | @interface AEAudioFileWriter : NSObject 48 | + (BOOL)AACEncodingAvailable; 49 | 50 | /*! 51 | * Initialise, with a given audio description to use 52 | * 53 | * @param audioDescription The audio format of audio that will be fed to this class 54 | * via the AddAudio functions. 55 | */ 56 | - (id)initWithAudioDescription:(AudioStreamBasicDescription)audioDescription; 57 | 58 | /*! 59 | * Begin write operation 60 | * 61 | * This will create the output file and prepare internal structures for writing. 62 | * 63 | * @param path The path to the file to create 64 | * @param fileType A file type 65 | * @param error On output, if not NULL, the error if one occurred 66 | * @return YES on success; NO on error 67 | */ 68 | - (BOOL)beginWritingToFileAtPath:(NSString*)path fileType:(AudioFileTypeID)fileType error:(NSError**)error; 69 | 70 | /*! 71 | * Complete writing operation 72 | * 73 | * Finishes write, closes the file and cleans up internal resources. 74 | */ 75 | - (void)finishWriting; 76 | 77 | /*! 78 | * Add audio to be written 79 | * 80 | * This C function, safe to be used in a Core Audio realtime thread context, is used to 81 | * feed audio to this class to be written to the file. 82 | * 83 | * It runs asynchronously, and will never block. 84 | * 85 | * @param writer A pointer to the writer object 86 | * @param bufferList An AudioBufferList containing the audio in the format you provided upon initialization 87 | * @param lengthInFrames The length of the audio in the buffer list, in frames 88 | * @return A status code; noErr on success 89 | */ 90 | OSStatus AEAudioFileWriterAddAudio(AEAudioFileWriter* writer, AudioBufferList *bufferList, UInt32 lengthInFrames); 91 | 92 | /*! 93 | * Add audio to be written, synchronously 94 | * 95 | * This C function allows you to synchronously add audio - it will block until the audio is written to the 96 | * file. Note that due to the fact that it will block, this function is not to be used from a Core Audio 97 | * realtime thread. 98 | * 99 | * @param writer A pointer to the writer object 100 | * @param bufferList An AudioBufferList containing the audio in the format you provided upon initialization 101 | * @param lengthInFrames The length of the audio in the buffer list, in frames 102 | * @return A status code; noErr on success 103 | */ 104 | OSStatus AEAudioFileWriterAddAudioSynchronously(AEAudioFileWriter* writer, AudioBufferList *bufferList, UInt32 lengthInFrames); 105 | 106 | /*! 107 | * The path to the file being written 108 | */ 109 | @property (nonatomic, strong, readonly) NSString *path; 110 | 111 | @end 112 | 113 | #ifdef __cplusplus 114 | } 115 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AERecorder.h: -------------------------------------------------------------------------------- 1 | // 2 | // AERecorder.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 23/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | extern NSString * AERecorderDidEncounterErrorNotification; 34 | extern NSString * kAERecorderErrorKey; 35 | 36 | /*! 37 | * Recorder utility, used for recording live audio to disk 38 | * 39 | * This can be used to record just the microphone input, or the output of the 40 | * audio system, just one channel, or a combination of all three. Simply add an 41 | * instance of this class as an audio receiver for the particular audio you wish 42 | * to record, using AEAudioController's [addInputReceiver:](@ref AEAudioController::addInputReceiver:), 43 | * [addOutputReceiver:](@ref AEAudioController::addOutputReceiver:), 44 | * [addOutputReceiver:forChannel:](@ref AEAudioController::addOutputReceiver:forChannel:), etc, and all 45 | * streams will be mixed together and recorded. 46 | * 47 | * See the sample app for a demonstration. 48 | */ 49 | @interface AERecorder : NSObject 50 | 51 | /*! 52 | * Determine whether AAC encoding is possible on this device 53 | */ 54 | + (BOOL)AACEncodingAvailable; 55 | 56 | /*! 57 | * Initialise 58 | * 59 | * @param audioController The Audio Controller 60 | */ 61 | - (id)initWithAudioController:(AEAudioController*)audioController; 62 | 63 | /*! 64 | * Prepare and begin recording 65 | * 66 | * Prepare to record, then start recording immediately, without 67 | * needing to call AERecorderStartRecording 68 | * 69 | * @param path The path to record to 70 | * @param fileType The kind of file to create 71 | * @param error The error, if not NULL and if an error occurs 72 | * @return YES on success, NO on failure. 73 | */ 74 | - (BOOL)beginRecordingToFileAtPath:(NSString*)path fileType:(AudioFileTypeID)fileType error:(NSError**)error; 75 | 76 | /*! 77 | * Prepare to record 78 | * 79 | * Prepare recording and set up internal data structures. 80 | * When this method returns, the recorder is ready to record. 81 | * 82 | * Start recording by calling AERecorderStartRecording. This allows 83 | * you to record synchronously with other audio events. 84 | * 85 | * @param path The path to record to 86 | * @param fileType The kind of file to create 87 | * @param error The error, if not NULL and if an error occurs 88 | * @return YES on success, NO on failure. 89 | */ 90 | - (BOOL)prepareRecordingToFileAtPath:(NSString*)path fileType:(AudioFileTypeID)fileType error:(NSError**)error; 91 | 92 | /*! 93 | * Start recording 94 | * 95 | * If you prepared recording by calling @link prepareRecordingToFileAtPath:fileType:error: @endlink, 96 | * call this method to actually begin recording. 97 | * 98 | * This is thread-safe and can be used from the audio thread. 99 | * 100 | * @param recorder The recorder 101 | */ 102 | void AERecorderStartRecording(AERecorder* recorder); 103 | 104 | /*! 105 | * Finish recording and close file 106 | */ 107 | - (void)finishRecording; 108 | 109 | /*! 110 | * The path 111 | */ 112 | @property (nonatomic, strong, readonly) NSString *path; 113 | 114 | /*! 115 | * Current recorded time in seconds 116 | */ 117 | @property (nonatomic, readonly) double currentTime; 118 | 119 | @end 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFileLoaderOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioFileLoaderOperation.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 17/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import 32 | 33 | @class AEAudioFileLoaderOperation; 34 | 35 | /*! 36 | * Audio file loader operation 37 | * 38 | * This in an NSOperation object that is used to load an arbitraty 39 | * audio file into memory. Use it by creating an instance, passing in 40 | * the file URL to the audio file, the audio description for the format 41 | * you the loaded audio in, optionally setting a completion block, and 42 | * adding the operation to an operation queue. 43 | * 44 | * If you wish to load a file synchronously, then you can simply start 45 | * the operation yourself, like so: 46 | * 47 | * @code 48 | * AEAudioFileLoaderOperation *operation = [[AEAudioFileLoaderOperation alloc] initWithFileURL:url 49 | * targetAudioDescription:audioDescription]; 50 | * [operation start]; 51 | * 52 | * if ( operation.error ) { 53 | * // Load failed! Clean up, report error, etc. 54 | * } else { 55 | * // Load finished - grab the audio 56 | * _bufferList = operation.bufferList; 57 | * _lengthInFrames = operation.lengthInFrames; 58 | * } 59 | * 60 | * [operation release]; // If not using ARC 61 | * @endcode 62 | * 63 | * Note that this class is not suitable for use with large audio files, 64 | * which should be loaded incrementally as playback occurs. 65 | */ 66 | @interface AEAudioFileLoaderOperation : NSOperation 67 | 68 | /*! 69 | * Get info for a file 70 | * 71 | * @param url URL to the file 72 | * @param audioDescription On output, if not NULL, will be filled with the file's audio description 73 | * @param lengthInFrames On output, if not NULL, will indicated the file length in frames 74 | * @param error If not NULL, and an error occurs, this contains the error that occurred 75 | * @return YES if file info was loaded successfully 76 | */ 77 | + (BOOL)infoForFileAtURL:(NSURL*)url audioDescription:(AudioStreamBasicDescription*)audioDescription lengthInFrames:(UInt32*)lengthInFrames error:(NSError**)error; 78 | 79 | /*! 80 | * Initializer 81 | * 82 | * @param url URL to the file to load 83 | * @param audioDescription The target audio description 84 | */ 85 | - (id)initWithFileURL:(NSURL*)url targetAudioDescription:(AudioStreamBasicDescription)audioDescription; 86 | 87 | /*! 88 | * A block to use to receive audio 89 | * 90 | * If this is set, then audio will be provided via this block as it is 91 | * loaded, instead of stored within @link bufferList @endlink. 92 | */ 93 | @property (nonatomic, copy) void (^audioReceiverBlock)(AudioBufferList *audio, UInt32 lengthInFrames); 94 | 95 | /*! 96 | * The loaded audio, once operation has completed, unless @link audioReceiverBlock @endlink is set. 97 | * 98 | * You are responsible for freeing both the memory pointed to by each mData pointer, 99 | * as well as the buffer list itself. If an error occurred, this will be NULL. 100 | */ 101 | @property (nonatomic, readonly) AudioBufferList *bufferList; 102 | 103 | /*! 104 | * The length of the audio file 105 | */ 106 | @property (nonatomic, readonly) UInt32 lengthInFrames; 107 | 108 | /*! 109 | * The error, if one occurred 110 | */ 111 | @property (nonatomic, strong, readonly) NSError *error; 112 | 113 | @end 114 | 115 | #ifdef __cplusplus 116 | } 117 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioUnitFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioUnitFilter.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 05/02/2013. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import "TheAmazingAudioEngine.h" 32 | 33 | /*! 34 | * Audio Unit Filter 35 | * 36 | * This class allows you to use Audio Units as filters. Provide an 37 | * AudioComponentDescription that describes the audio unit, and the 38 | * corresponding audio unit will be initialised, ready for use 39 | * 40 | */ 41 | @interface AEAudioUnitFilter : NSObject 42 | 43 | /*! 44 | * Create a new Audio Unit filter 45 | * 46 | * @param audioComponentDescription The structure that identifies the audio unit 47 | * @param audioController The audio controller 48 | * @param error On output, if not NULL, will point to an error if a problem occurred 49 | * @return The initialised filter, or nil if an error occurred 50 | */ 51 | - (id)initWithComponentDescription:(AudioComponentDescription)audioComponentDescription 52 | audioController:(AEAudioController*)audioController 53 | error:(NSError**)error; 54 | 55 | /*! 56 | * Create a new Audio Unit filter, using the default input audio description 57 | * 58 | * @param audioComponentDescription The structure that identifies the audio unit 59 | * @param audioController The audio controller 60 | * @param useDefaultInputFormat Whether to always use the audio unit's default input audio format. 61 | * This can be used as a workaround for audio units that misidentify the TAAE system 62 | * audio description as being compatible. Audio will automatically be converted from 63 | * the source audio format to this format. 64 | * @param error On output, if not NULL, will point to an error if a problem occurred 65 | * @return The initialised filter, or nil if an error occurred 66 | */ 67 | - (id)initWithComponentDescription:(AudioComponentDescription)audioComponentDescription 68 | audioController:(AEAudioController*)audioController 69 | useDefaultInputFormat:(BOOL)useDefaultInputFormat 70 | error:(NSError**)error; 71 | 72 | /*! 73 | * Create a new Audio Unit filter, with a block to run before initialization of the unit 74 | * 75 | * @param audioComponentDescription The structure that identifies the audio unit 76 | * @param audioController The audio controller 77 | * @param useDefaultInputFormat Whether to always use the audio unit's default input audio format. 78 | * This can be used as a workaround for audio units that misidentify the TAAE system 79 | * audio description as being compatible. Audio will automatically be converted from 80 | * the source audio format to this format. 81 | * @param preInitializeBlock A block to run before the audio unit is initialized. 82 | * This can be used to set some properties that needs to be set before the unit is initialized. 83 | * @param error On output, if not NULL, will point to an error if a problem occurred 84 | * @return The initialised filter, or nil if an error occurred 85 | */ 86 | - (id)initWithComponentDescription:(AudioComponentDescription)audioComponentDescription 87 | audioController:(AEAudioController*)audioController 88 | useDefaultInputFormat:(BOOL)useDefaultInputFormat 89 | preInitializeBlock:(void(^)(AudioUnit audioUnit))block 90 | error:(NSError**)error; 91 | 92 | 93 | /*! 94 | * The audio unit 95 | */ 96 | @property (nonatomic, readonly) AudioUnit audioUnit; 97 | 98 | /*! 99 | * The audio graph node 100 | */ 101 | @property (nonatomic, readonly) AUNode audioGraphNode; 102 | 103 | /*! 104 | * Audio Unit effect bypass. Default is false. 105 | * Toggle this state at any time and it will begin taking effect 106 | * on the next render cycle. 107 | */ 108 | @property (nonatomic, assign) bool bypassed; 109 | 110 | @end 111 | 112 | #ifdef __cplusplus 113 | } 114 | #endif 115 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEUtilities.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Michael Tyson on 23/03/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /*! 33 | * Allocate an audio buffer list and the associated mData pointers. 34 | * 35 | * Note: Do not use this utility from within the Core Audio thread (such as inside a render 36 | * callback). It may cause the thread to block, inducing audio stutters. 37 | * 38 | * @param audioFormat Audio format describing audio to be stored in buffer list 39 | * @param frameCount The number of frames to allocate space for (or 0 to just allocate the list structure itself) 40 | * @return The allocated and initialised audio buffer list 41 | */ 42 | AudioBufferList *AEAllocateAndInitAudioBufferList(AudioStreamBasicDescription audioFormat, int frameCount); 43 | 44 | /*! 45 | * Create a copy of an audio buffer list 46 | * 47 | * Note: Do not use this utility from within the Core Audio thread (such as inside a render 48 | * callback). It may cause the thread to block, inducing audio stutters. 49 | * 50 | * @param original The original AudioBufferList to copy 51 | * @return The new, copied audio buffer list 52 | */ 53 | AudioBufferList *AECopyAudioBufferList(AudioBufferList *original); 54 | 55 | /*! 56 | * Free a buffer list and associated mData buffers 57 | * 58 | * Note: Do not use this utility from within the Core Audio thread (such as inside a render 59 | * callback). It may cause the thread to block, inducing audio stutters. 60 | */ 61 | void AEFreeAudioBufferList(AudioBufferList *bufferList); 62 | 63 | /*! 64 | * Initialize a pre-allocated audio buffer list structure 65 | * 66 | * Populates the fields in the given audio buffer list. This utility is useful when 67 | * allocating an audio buffer list on the stack. 68 | * 69 | * Sample usage: 70 | * 71 | * @code 72 | * char audioBufferListSpace[sizeof(AudioBufferList)+sizeof(AudioBuffer)]; 73 | * AudioBufferList *bufferList = (AudioBufferList*)audioBufferListSpace; 74 | * AEInitAudioBufferList(bufferList, sizeof(audioBufferListSpace), &THIS->_audioFormat, THIS->_audioBytes, kAudioBufferSize); 75 | * @endcode 76 | * 77 | * @param list Audio buffer list to initialize 78 | * @param listSize Size of buffer list structure (eg. "sizeof(list)") 79 | * @param audioFormat Audio format describing audio to be stored in buffer list 80 | * @param data Optional pointer to a buffer to point the mData pointers within buffer list to. 81 | * If audio format is more than one channel and non-interleaved, the buffer will be 82 | * broken up into even pieces, one for each channel. 83 | * @param dataSize Size of 'data' buffer, in bytes. 84 | */ 85 | void AEInitAudioBufferList(AudioBufferList *list, int listSize, AudioStreamBasicDescription audioFormat, void *data, int dataSize); 86 | 87 | 88 | /*! 89 | * Get the number of frames in a buffer list 90 | * 91 | * Calculates the frame count in the buffer list based on the given 92 | * audio format. Optionally also provides the channel count. 93 | * 94 | * @param list Pointer to an AudioBufferList containing audio 95 | * @param audioFormat Audio format describing the audio in the buffer list 96 | * @param oNumberOfChannels If not NULL, will be set to the number of channels of audio in 'list' 97 | * @return Number of frames in the buffer list 98 | */ 99 | int AEGetNumberOfFramesInAudioBufferList(AudioBufferList *list, AudioStreamBasicDescription audioFormat, int *oNumberOfChannels); 100 | 101 | 102 | /*! 103 | * Create an AudioComponentDescription structure 104 | * 105 | * @param manufacturer The audio component manufacturer (e.g. kAudioUnitManufacturer_Apple) 106 | * @param type The type (e.g. kAudioUnitType_Generator) 107 | * @param subtype The subtype (e.g. kAudioUnitSubType_AudioFilePlayer) 108 | * @returns An AudioComponentDescription structure with the given attributes 109 | */ 110 | AudioComponentDescription AEAudioComponentDescriptionMake(OSType manufacturer, OSType type, OSType subtype); 111 | 112 | /*! 113 | * Assign a channel count to an AudioStreamBasicDescription 114 | * 115 | * This method ensures that the mBytesPerFrame/mBytesPerPacket value is updated 116 | * correctly for interleaved audio. 117 | */ 118 | void AEAudioStreamBasicDescriptionSetChannelsPerFrame(AudioStreamBasicDescription *audioDescription, int numberOfChannels); 119 | 120 | #ifdef __cplusplus 121 | } 122 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEFloatConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEFloatConverter.h 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Michael Tyson on 25/10/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import 32 | 33 | /*! 34 | * Universal converter to float format 35 | * 36 | * Use this class to easily convert arbitrary audio formats to floating point 37 | * for use with utilities like the Accelerate framework. 38 | */ 39 | @interface AEFloatConverter : NSObject 40 | 41 | /*! 42 | * Initialize 43 | * 44 | * @param sourceFormat The audio format to use 45 | */ 46 | - (id)initWithSourceFormat:(AudioStreamBasicDescription)sourceFormat; 47 | 48 | /*! 49 | * Convert audio to floating-point 50 | * 51 | * This C function, safe to use in a Core Audio realtime thread context, will take 52 | * an audio buffer list of audio in the format you provided at initialisation, and 53 | * convert it into a noninterleaved float array. 54 | * 55 | * @param converter Pointer to the converter object. 56 | * @param sourceBuffer An audio buffer list containing the source audio. 57 | * @param targetBuffers An array of floating-point arrays to store the converted float audio into. 58 | * Note that you must provide the correct number of arrays, to match the number of channels. 59 | * @param frames The number of frames to convert. 60 | * @return YES on success; NO on failure 61 | */ 62 | BOOL AEFloatConverterToFloat(AEFloatConverter* converter, AudioBufferList *sourceBuffer, float * const * targetBuffers, UInt32 frames); 63 | 64 | /*! 65 | * Convert audio to floating-point, in a buffer list 66 | * 67 | * This C function, safe to use in a Core Audio realtime thread context, will take 68 | * an audio buffer list of audio in the format you provided at initialisation, and 69 | * convert it into a noninterleaved float format. 70 | * 71 | * @param converter Pointer to the converter object. 72 | * @param sourceBuffer An audio buffer list containing the source audio. 73 | * @param targetBuffer An audio buffer list to store the converted floating-point audio. 74 | * @param frames The number of frames to convert. 75 | * @return YES on success; NO on failure 76 | */ 77 | BOOL AEFloatConverterToFloatBufferList(AEFloatConverter* converter, AudioBufferList *sourceBuffer, AudioBufferList *targetBuffer, UInt32 frames); 78 | 79 | /*! 80 | * Convert audio from floating-point 81 | * 82 | * This C function, safe to use in a Core Audio realtime thread context, will take 83 | * an audio buffer list of audio in the format you provided at initialisation, and 84 | * convert it into a float array. 85 | * 86 | * @param converter Pointer to the converter object. 87 | * @param sourceBuffers An array of floating-point arrays containing the floating-point audio to convert. 88 | * Note that you must provide the correct number of arrays, to match the number of channels. 89 | * @param targetBuffer An audio buffer list to store the converted audio into. 90 | * @param frames The number of frames to convert. 91 | * @return YES on success; NO on failure 92 | */ 93 | BOOL AEFloatConverterFromFloat(AEFloatConverter* converter, float * const * sourceBuffers, AudioBufferList *targetBuffer, UInt32 frames); 94 | 95 | /*! 96 | * Convert audio from floating-point, in a buffer list 97 | * 98 | * This C function, safe to use in a Core Audio realtime thread context, will take 99 | * an audio buffer list of audio in the format you provided at initialisation, and 100 | * convert it into a float array. 101 | * 102 | * @param converter Pointer to the converter object. 103 | * @param sourceBuffer An audio buffer list containing the source audio. 104 | * @param targetBuffer An audio buffer list to store the converted audio into. 105 | * @param frames The number of frames to convert. 106 | * @return YES on success; NO on failure 107 | */ 108 | BOOL AEFloatConverterFromFloatBufferList(AEFloatConverter* converter, AudioBufferList *sourceBuffer, AudioBufferList *targetBuffer, UInt32 frames); 109 | 110 | /*! 111 | * The AudioStreamBasicDescription representing the converted floating-point format 112 | */ 113 | @property (nonatomic, readonly) AudioStreamBasicDescription floatingPointAudioDescription; 114 | 115 | /*! 116 | * The source audio format set at initialization 117 | */ 118 | @property (nonatomic, assign) AudioStreamBasicDescription sourceFormat; 119 | 120 | /*! 121 | * The number of channels for the floating-point format 122 | */ 123 | @property (nonatomic, assign) int floatFormatChannelsPerFrame; 124 | 125 | @end 126 | 127 | #ifdef __cplusplus 128 | } 129 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEUtilities.c: -------------------------------------------------------------------------------- 1 | // 2 | // AEUtilities.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Michael Tyson on 23/03/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #include "AEUtilities.h" 27 | 28 | AudioBufferList *AEAllocateAndInitAudioBufferList(AudioStreamBasicDescription audioFormat, int frameCount) { 29 | int numberOfBuffers = audioFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved ? audioFormat.mChannelsPerFrame : 1; 30 | int channelsPerBuffer = audioFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved ? 1 : audioFormat.mChannelsPerFrame; 31 | int bytesPerBuffer = audioFormat.mBytesPerFrame * frameCount; 32 | 33 | AudioBufferList *audio = malloc(sizeof(AudioBufferList) + (numberOfBuffers-1)*sizeof(AudioBuffer)); 34 | if ( !audio ) { 35 | return NULL; 36 | } 37 | audio->mNumberBuffers = numberOfBuffers; 38 | for ( int i=0; i 0 ) { 40 | audio->mBuffers[i].mData = calloc(bytesPerBuffer, 1); 41 | if ( !audio->mBuffers[i].mData ) { 42 | for ( int j=0; jmBuffers[j].mData); 43 | free(audio); 44 | return NULL; 45 | } 46 | } else { 47 | audio->mBuffers[i].mData = NULL; 48 | } 49 | audio->mBuffers[i].mDataByteSize = bytesPerBuffer; 50 | audio->mBuffers[i].mNumberChannels = channelsPerBuffer; 51 | } 52 | return audio; 53 | } 54 | 55 | AudioBufferList *AECopyAudioBufferList(AudioBufferList *original) { 56 | AudioBufferList *audio = malloc(sizeof(AudioBufferList) + (original->mNumberBuffers-1)*sizeof(AudioBuffer)); 57 | if ( !audio ) { 58 | return NULL; 59 | } 60 | audio->mNumberBuffers = original->mNumberBuffers; 61 | for ( int i=0; imNumberBuffers; i++ ) { 62 | audio->mBuffers[i].mData = malloc(original->mBuffers[i].mDataByteSize); 63 | if ( !audio->mBuffers[i].mData ) { 64 | for ( int j=0; jmBuffers[j].mData); 65 | free(audio); 66 | return NULL; 67 | } 68 | audio->mBuffers[i].mDataByteSize = original->mBuffers[i].mDataByteSize; 69 | audio->mBuffers[i].mNumberChannels = original->mBuffers[i].mNumberChannels; 70 | memcpy(audio->mBuffers[i].mData, original->mBuffers[i].mData, original->mBuffers[i].mDataByteSize); 71 | } 72 | return audio; 73 | } 74 | 75 | void AEFreeAudioBufferList(AudioBufferList *bufferList ) { 76 | for ( int i=0; imNumberBuffers; i++ ) { 77 | if ( bufferList->mBuffers[i].mData ) free(bufferList->mBuffers[i].mData); 78 | } 79 | free(bufferList); 80 | } 81 | 82 | void AEInitAudioBufferList(AudioBufferList *list, int listSize, AudioStreamBasicDescription audioFormat, void *data, int dataSize) { 83 | list->mNumberBuffers = audioFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved ? audioFormat.mChannelsPerFrame : 1; 84 | assert(list->mNumberBuffers == 1 || listSize >= (sizeof(AudioBufferList)+sizeof(AudioBuffer)) ); 85 | 86 | for ( int i=0; imNumberBuffers; i++ ) { 87 | list->mBuffers[0].mNumberChannels = audioFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved ? 1 : audioFormat.mChannelsPerFrame; 88 | list->mBuffers[0].mData = (char*)data + (i * (dataSize/list->mNumberBuffers)); 89 | list->mBuffers[0].mDataByteSize = dataSize/list->mNumberBuffers; 90 | } 91 | } 92 | 93 | int AEGetNumberOfFramesInAudioBufferList(AudioBufferList *list, AudioStreamBasicDescription audioFormat, int *oNumberOfChannels) { 94 | int channelCount = audioFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved ? list->mNumberBuffers : list->mBuffers[0].mNumberChannels; 95 | if ( oNumberOfChannels ) { 96 | *oNumberOfChannels = channelCount; 97 | } 98 | return list->mBuffers[0].mDataByteSize / ((audioFormat.mBitsPerChannel/8) * channelCount); 99 | } 100 | 101 | AudioComponentDescription AEAudioComponentDescriptionMake(OSType manufacturer, OSType type, OSType subtype) { 102 | AudioComponentDescription description; 103 | memset(&description, 0, sizeof(description)); 104 | description.componentManufacturer = manufacturer; 105 | description.componentType = type; 106 | description.componentSubType = subtype; 107 | return description; 108 | } 109 | 110 | void AEAudioStreamBasicDescriptionSetChannelsPerFrame(AudioStreamBasicDescription *audioDescription, int numberOfChannels) { 111 | if ( !(audioDescription->mFormatFlags & kAudioFormatFlagIsNonInterleaved) ) { 112 | audioDescription->mBytesPerFrame *= (float)numberOfChannels / (float)audioDescription->mChannelsPerFrame; 113 | audioDescription->mBytesPerPacket *= (float)numberOfChannels / (float)audioDescription->mChannelsPerFrame; 114 | } 115 | audioDescription->mChannelsPerFrame = numberOfChannels; 116 | } -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AELimiterFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // AELimiterFilter.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 21/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AELimiterFilter.h" 27 | #import "AELimiter.h" 28 | #import "AEFloatConverter.h" 29 | #import 30 | 31 | const int kScratchBufferLength = 8192; 32 | 33 | @interface AELimiterFilter () { 34 | float **_scratchBuffer; 35 | } 36 | @property (nonatomic, strong) AEFloatConverter *floatConverter; 37 | @property (nonatomic, strong) AELimiter *limiter; 38 | @property (nonatomic, weak) AEAudioController *audioController; 39 | @end 40 | 41 | @implementation AELimiterFilter 42 | @synthesize floatConverter = _floatConverter, limiter = _limiter, clientFormat = _clientFormat, audioController = _audioController; 43 | @dynamic hold, attack, decay, level; 44 | 45 | - (id)initWithAudioController:(AEAudioController *)audioController { 46 | if ( !(self = [super init]) ) return nil; 47 | 48 | self.audioController = audioController; 49 | _clientFormat = audioController.audioDescription; 50 | self.floatConverter = [[AEFloatConverter alloc] initWithSourceFormat:_clientFormat]; 51 | self.limiter = [[AELimiter alloc] initWithNumberOfChannels:_clientFormat.mChannelsPerFrame sampleRate:_clientFormat.mSampleRate]; 52 | 53 | _scratchBuffer = (float**)malloc(sizeof(float*) * _clientFormat.mChannelsPerFrame); 54 | assert(_scratchBuffer); 55 | for ( int i=0; i<_clientFormat.mChannelsPerFrame; i++ ) { 56 | _scratchBuffer[i] = malloc(sizeof(float) * kScratchBufferLength); 57 | assert(_scratchBuffer[i]); 58 | } 59 | 60 | return self; 61 | } 62 | 63 | -(void)dealloc { 64 | for ( int i=0; i<_clientFormat.mChannelsPerFrame; i++ ) { 65 | free(_scratchBuffer[i]); 66 | } 67 | free(_scratchBuffer); 68 | self.audioController = nil; 69 | } 70 | 71 | -(void)setClientFormat:(AudioStreamBasicDescription)clientFormat { 72 | 73 | AEFloatConverter *floatConverter = [[AEFloatConverter alloc] initWithSourceFormat:clientFormat]; 74 | 75 | float **scratchBuffer = (float**)malloc(sizeof(float*) * clientFormat.mChannelsPerFrame); 76 | assert(scratchBuffer); 77 | for ( int i=0; i_floatConverter, audio, THIS->_scratchBuffer, frames); 147 | 148 | AELimiterEnqueue(THIS->_limiter, THIS->_scratchBuffer, frames, NULL); 149 | AELimiterDequeue(THIS->_limiter, THIS->_scratchBuffer, &frames, NULL); 150 | 151 | if ( frames > 0 ) { 152 | // Convert back to buffer 153 | AEFloatConverterFromFloat(THIS->_floatConverter, THIS->_scratchBuffer, audio, frames); 154 | } 155 | 156 | return noErr; 157 | } 158 | 159 | -(AEAudioControllerFilterCallback)filterCallback { 160 | return filterCallback; 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AERecorder.m: -------------------------------------------------------------------------------- 1 | // 2 | // AERecorder.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 23/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AERecorder.h" 27 | #import "AEMixerBuffer.h" 28 | #import "AEAudioFileWriter.h" 29 | 30 | #define kProcessChunkSize 8192 31 | 32 | NSString * AERecorderDidEncounterErrorNotification = @"AERecorderDidEncounterErrorNotification"; 33 | NSString * kAERecorderErrorKey = @"error"; 34 | 35 | @interface AERecorder () { 36 | BOOL _recording; 37 | AudioBufferList *_buffer; 38 | } 39 | @property (nonatomic, strong) AEMixerBuffer *mixer; 40 | @property (nonatomic, strong) AEAudioFileWriter *writer; 41 | @end 42 | 43 | @implementation AERecorder 44 | @synthesize mixer = _mixer, writer = _writer, currentTime = _currentTime; 45 | @dynamic path; 46 | 47 | + (BOOL)AACEncodingAvailable { 48 | return [AEAudioFileWriter AACEncodingAvailable]; 49 | } 50 | 51 | - (id)initWithAudioController:(AEAudioController*)audioController { 52 | if ( !(self = [super init]) ) return nil; 53 | self.mixer = [[AEMixerBuffer alloc] initWithClientFormat:audioController.audioDescription]; 54 | self.writer = [[AEAudioFileWriter alloc] initWithAudioDescription:audioController.audioDescription]; 55 | if ( audioController.audioInputAvailable && audioController.inputAudioDescription.mChannelsPerFrame != audioController.audioDescription.mChannelsPerFrame ) { 56 | [_mixer setAudioDescription:*AEAudioControllerInputAudioDescription(audioController) forSource:AEAudioSourceInput]; 57 | } 58 | _buffer = AEAllocateAndInitAudioBufferList(audioController.audioDescription, 0); 59 | 60 | return self; 61 | } 62 | 63 | -(void)dealloc { 64 | free(_buffer); 65 | } 66 | 67 | -(BOOL)beginRecordingToFileAtPath:(NSString *)path fileType:(AudioFileTypeID)fileType error:(NSError **)error { 68 | BOOL result = [self prepareRecordingToFileAtPath:path fileType:fileType error:error]; 69 | _recording = YES; 70 | return result; 71 | } 72 | 73 | - (BOOL)prepareRecordingToFileAtPath:(NSString*)path fileType:(AudioFileTypeID)fileType error:(NSError**)error { 74 | _currentTime = 0.0; 75 | BOOL result = [_writer beginWritingToFileAtPath:path fileType:fileType error:error]; 76 | return result; 77 | } 78 | 79 | void AERecorderStartRecording(__unsafe_unretained AERecorder* THIS) { 80 | THIS->_recording = YES; 81 | } 82 | 83 | - (void)finishRecording { 84 | _recording = NO; 85 | [_writer finishWriting]; 86 | } 87 | 88 | -(NSString *)path { 89 | return _writer.path; 90 | } 91 | 92 | struct reportError_t { void *THIS; OSStatus result; }; 93 | static void reportError(AEAudioController *audioController, void *userInfo, int length) { 94 | struct reportError_t *arg = userInfo; 95 | NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain 96 | code:arg->result 97 | userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedString(@"Error while saving audio: Code %d", @""), arg->result]}]; 98 | [[NSNotificationCenter defaultCenter] postNotificationName:AERecorderDidEncounterErrorNotification 99 | object:(__bridge id)arg->THIS 100 | userInfo:@{kAERecorderErrorKey: error}]; 101 | } 102 | 103 | static void audioCallback(__unsafe_unretained AERecorder *THIS, 104 | __unsafe_unretained AEAudioController *audioController, 105 | void *source, 106 | const AudioTimeStamp *time, 107 | UInt32 frames, 108 | AudioBufferList *audio) { 109 | if ( !THIS->_recording ) return; 110 | 111 | AEMixerBufferEnqueue(THIS->_mixer, source, audio, frames, time); 112 | 113 | // Let the mixer buffer provide the audio buffer 114 | UInt32 bufferLength = kProcessChunkSize; 115 | for ( int i=0; i_buffer->mNumberBuffers; i++ ) { 116 | THIS->_buffer->mBuffers[i].mData = NULL; 117 | THIS->_buffer->mBuffers[i].mDataByteSize = 0; 118 | } 119 | 120 | THIS->_currentTime += AEConvertFramesToSeconds(audioController, frames); 121 | 122 | AEMixerBufferDequeue(THIS->_mixer, THIS->_buffer, &bufferLength, NULL); 123 | 124 | if ( bufferLength > 0 ) { 125 | OSStatus status = AEAudioFileWriterAddAudio(THIS->_writer, THIS->_buffer, bufferLength); 126 | if ( status != noErr ) { 127 | AEAudioControllerSendAsynchronousMessageToMainThread(audioController, 128 | reportError, 129 | &(struct reportError_t) { .THIS = (__bridge void*)THIS, .result = status }, 130 | sizeof(struct reportError_t)); 131 | } 132 | } 133 | } 134 | 135 | -(AEAudioControllerAudioCallback)receiverCallback { 136 | return audioCallback; 137 | } 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/Library/TPCircularBuffer/TPCircularBuffer.c: -------------------------------------------------------------------------------- 1 | // 2 | // TPCircularBuffer.c 3 | // Circular/Ring buffer implementation 4 | // 5 | // https://github.com/michaeltyson/TPCircularBuffer 6 | // 7 | // Created by Michael Tyson on 10/12/2011. 8 | // 9 | // Copyright (C) 2012-2013 A Tasty Pixel 10 | // 11 | // This software is provided 'as-is', without any express or implied 12 | // warranty. In no event will the authors be held liable for any damages 13 | // arising from the use of this software. 14 | // 15 | // Permission is granted to anyone to use this software for any purpose, 16 | // including commercial applications, and to alter it and redistribute it 17 | // freely, subject to the following restrictions: 18 | // 19 | // 1. The origin of this software must not be misrepresented; you must not 20 | // claim that you wrote the original software. If you use this software 21 | // in a product, an acknowledgment in the product documentation would be 22 | // appreciated but is not required. 23 | // 24 | // 2. Altered source versions must be plainly marked as such, and must not be 25 | // misrepresented as being the original software. 26 | // 27 | // 3. This notice may not be removed or altered from any source distribution. 28 | // 29 | 30 | #include "TPCircularBuffer.h" 31 | #include 32 | #include 33 | 34 | #define reportResult(result,operation) (_reportResult((result),(operation),strrchr(__FILE__, '/')+1,__LINE__)) 35 | static inline bool _reportResult(kern_return_t result, const char *operation, const char* file, int line) { 36 | if ( result != ERR_SUCCESS ) { 37 | printf("%s:%d: %s: %s\n", file, line, operation, mach_error_string(result)); 38 | return false; 39 | } 40 | return true; 41 | } 42 | 43 | bool TPCircularBufferInit(TPCircularBuffer *buffer, int length) { 44 | 45 | // Keep trying until we get our buffer, needed to handle race conditions 46 | int retries = 3; 47 | while ( true ) { 48 | 49 | buffer->length = (int32_t)round_page(length); // We need whole page sizes 50 | 51 | // Temporarily allocate twice the length, so we have the contiguous address space to 52 | // support a second instance of the buffer directly after 53 | vm_address_t bufferAddress; 54 | kern_return_t result = vm_allocate(mach_task_self(), 55 | &bufferAddress, 56 | buffer->length * 2, 57 | VM_FLAGS_ANYWHERE); // allocate anywhere it'll fit 58 | if ( result != ERR_SUCCESS ) { 59 | if ( retries-- == 0 ) { 60 | reportResult(result, "Buffer allocation"); 61 | return false; 62 | } 63 | // Try again if we fail 64 | continue; 65 | } 66 | 67 | // Now replace the second half of the allocation with a virtual copy of the first half. Deallocate the second half... 68 | result = vm_deallocate(mach_task_self(), 69 | bufferAddress + buffer->length, 70 | buffer->length); 71 | if ( result != ERR_SUCCESS ) { 72 | if ( retries-- == 0 ) { 73 | reportResult(result, "Buffer deallocation"); 74 | return false; 75 | } 76 | // If this fails somehow, deallocate the whole region and try again 77 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 78 | continue; 79 | } 80 | 81 | // Re-map the buffer to the address space immediately after the buffer 82 | vm_address_t virtualAddress = bufferAddress + buffer->length; 83 | vm_prot_t cur_prot, max_prot; 84 | result = vm_remap(mach_task_self(), 85 | &virtualAddress, // mirror target 86 | buffer->length, // size of mirror 87 | 0, // auto alignment 88 | 0, // force remapping to virtualAddress 89 | mach_task_self(), // same task 90 | bufferAddress, // mirror source 91 | 0, // MAP READ-WRITE, NOT COPY 92 | &cur_prot, // unused protection struct 93 | &max_prot, // unused protection struct 94 | VM_INHERIT_DEFAULT); 95 | if ( result != ERR_SUCCESS ) { 96 | if ( retries-- == 0 ) { 97 | reportResult(result, "Remap buffer memory"); 98 | return false; 99 | } 100 | // If this remap failed, we hit a race condition, so deallocate and try again 101 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 102 | continue; 103 | } 104 | 105 | if ( virtualAddress != bufferAddress+buffer->length ) { 106 | // If the memory is not contiguous, clean up both allocated buffers and try again 107 | if ( retries-- == 0 ) { 108 | printf("Couldn't map buffer memory to end of buffer\n"); 109 | return false; 110 | } 111 | 112 | vm_deallocate(mach_task_self(), virtualAddress, buffer->length); 113 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 114 | continue; 115 | } 116 | 117 | buffer->buffer = (void*)bufferAddress; 118 | buffer->fillCount = 0; 119 | buffer->head = buffer->tail = 0; 120 | 121 | return true; 122 | } 123 | return false; 124 | } 125 | 126 | void TPCircularBufferCleanup(TPCircularBuffer *buffer) { 127 | vm_deallocate(mach_task_self(), (vm_address_t)buffer->buffer, buffer->length * 2); 128 | memset(buffer, 0, sizeof(TPCircularBuffer)); 129 | } 130 | 131 | void TPCircularBufferClear(TPCircularBuffer *buffer) { 132 | int32_t fillCount; 133 | if ( TPCircularBufferTail(buffer, &fillCount) ) { 134 | TPCircularBufferConsume(buffer, fillCount); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /AmazingSequencer/SimpleDemoVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleDemoVC.m 3 | // AmazingSequencer 4 | // 5 | // Created by Ariel Elkin on 07/04/2015. 6 | // Copyright (c) 2015 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import "SimpleDemoVC.h" 10 | 11 | #import "AESequencerChannel.h" 12 | #import "AESequencerChannelSequence.h" 13 | #import "AESequencerBeat.h" 14 | 15 | @implementation SimpleDemoVC { 16 | AEAudioController *audioController; 17 | AESequencerChannel *woodBlockSoundChannel; 18 | AESequencerChannel *crickSoundChannel; 19 | } 20 | 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | [self setupUI]; 26 | 27 | // Init the AEAudioController: 28 | audioController = [[AEAudioController alloc] initWithAudioDescription:[AEAudioController nonInterleavedFloatStereoAudioDescription]]; 29 | 30 | // Start it: 31 | NSError *audioControllerStartError = nil; 32 | [audioController start:&audioControllerStartError]; 33 | if (audioControllerStartError) { 34 | NSLog(@"Audio controller start error: %@", audioControllerStartError.localizedDescription); 35 | } 36 | 37 | 38 | //Find the NSURL of your audio file: 39 | NSURL *woodblockSoundURL = [[NSBundle mainBundle] URLForResource:@"woodblock" withExtension:@"caf"]; 40 | 41 | //Specify at which times it should play: 42 | AESequencerChannelSequence *woodblockSoundSequence = [AESequencerChannelSequence new]; 43 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0]]; 44 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0.25]]; 45 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0.50]]; 46 | [woodblockSoundSequence addBeat:[AESequencerBeat beatWithOnset:0.75]]; 47 | 48 | 49 | //Create a channel that will play the sequence: 50 | woodBlockSoundChannel = [AESequencerChannel sequencerChannelWithAudioFileAt:woodblockSoundURL 51 | audioController:audioController 52 | withSequence:woodblockSoundSequence 53 | numberOfFullBeatsPerMeasure:4 54 | atBPM:120]; 55 | 56 | 57 | //Add it to the audio controller: 58 | [audioController addChannels:@[woodBlockSoundChannel]]; 59 | 60 | 61 | //Tell it to start playing: 62 | woodBlockSoundChannel.sequenceIsPlaying = true; 63 | 64 | 65 | 66 | //How about something more complex? 67 | 68 | NSURL *crickSoundURL = [[NSBundle mainBundle] URLForResource:@"crick" withExtension:@"caf"]; 69 | AESequencerChannelSequence *crickSoundSequence= [AESequencerChannelSequence new]; 70 | [crickSoundSequence addBeat:[AESequencerBeat beatWithOnset:1.0 / 4 + 2.0 / 16 velocity:0.25 ]]; 71 | [crickSoundSequence addBeat:[AESequencerBeat beatWithOnset:2.0 / 4 + 1.0 / 16 velocity:0.5 ]]; 72 | [crickSoundSequence addBeat:[AESequencerBeat beatWithOnset:2.0 / 4 + 2.0 / 16 velocity:0.125 ]]; 73 | [crickSoundSequence addBeat:[AESequencerBeat beatWithOnset:2.0 / 4 + 3.0 / 16 velocity:0.5 ]]; 74 | [crickSoundSequence addBeat:[AESequencerBeat beatWithOnset:3.0 / 4 + 1.0 / 8 velocity:0.5 ]]; 75 | 76 | crickSoundChannel = [AESequencerChannel sequencerChannelWithAudioFileAt:crickSoundURL 77 | audioController:audioController 78 | withSequence:crickSoundSequence 79 | numberOfFullBeatsPerMeasure:4 80 | atBPM:120]; 81 | [audioController addChannels:@[crickSoundChannel]]; 82 | 83 | 84 | crickSoundChannel.sequenceIsPlaying = true; 85 | } 86 | 87 | 88 | - (void)setupUI { 89 | 90 | UILabel *label = [UILabel new]; 91 | label.text = @"The Amazing Audio Engine Sequencer - Simple Demo"; 92 | label.font = [UIFont systemFontOfSize:30]; 93 | label.textAlignment = NSTextAlignmentCenter; 94 | label.translatesAutoresizingMaskIntoConstraints = NO; 95 | [self.view addSubview:label]; 96 | 97 | UIButton *backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 98 | [backButton setTitle:@"Back" forState:UIControlStateNormal]; 99 | backButton.titleLabel.font = [UIFont systemFontOfSize:30]; 100 | [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 101 | backButton.backgroundColor = [UIColor blueColor]; 102 | backButton.translatesAutoresizingMaskIntoConstraints = NO; 103 | [backButton addTarget:self action:@selector(dismissModalViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside]; 104 | [self.view addSubview:backButton]; 105 | 106 | NSDictionary *views = @{@"label": label, @"backButton":backButton}; 107 | 108 | NSArray *labelConstraints = [NSLayoutConstraint 109 | constraintsWithVisualFormat:@"H:|-[label]-|" 110 | options:0 111 | metrics:nil 112 | views:views]; 113 | [self.view addConstraints:labelConstraints]; 114 | 115 | 116 | labelConstraints = [NSLayoutConstraint 117 | constraintsWithVisualFormat:@"V:|-200-[label]" 118 | options:0 119 | metrics:nil 120 | views:views]; 121 | [self.view addConstraints:labelConstraints]; 122 | 123 | 124 | 125 | NSArray *backButtonConstraints = [NSLayoutConstraint 126 | constraintsWithVisualFormat:@"H:|-[backButton(200)]" 127 | options:0 128 | metrics:nil 129 | views:views]; 130 | [self.view addConstraints:backButtonConstraints]; 131 | 132 | backButtonConstraints = [NSLayoutConstraint 133 | constraintsWithVisualFormat:@"V:|-20-[backButton(100)]" 134 | options:0 135 | metrics:nil 136 | views:views]; 137 | [self.view addConstraints:backButtonConstraints]; 138 | 139 | 140 | } 141 | 142 | 143 | - (void)viewWillDisappear:(BOOL)animated { 144 | crickSoundChannel.sequenceIsPlaying = false; 145 | [audioController stop]; 146 | } 147 | 148 | @end 149 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AEPlaythroughChannel.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEPlaythroughChannel.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 21/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AEPlaythroughChannel.h" 27 | #import "TPCircularBuffer.h" 28 | #import "TPCircularBuffer+AudioBufferList.h" 29 | #import "AEAudioController+Audiobus.h" 30 | #import "AEAudioController+AudiobusStub.h" 31 | 32 | static const int kAudioBufferLength = 16384; 33 | static const int kAudiobusReceiverPortConnectedToSelfChanged; 34 | 35 | @interface AEPlaythroughChannel () { 36 | TPCircularBuffer _buffer; 37 | BOOL _audiobusConnectedToSelf; 38 | } 39 | @property (nonatomic, strong) AEAudioController *audioController; 40 | @end 41 | 42 | @implementation AEPlaythroughChannel 43 | @synthesize audioController=_audioController, volume = _volume; 44 | 45 | +(NSSet *)keyPathsForValuesAffectingAudioDescription { 46 | return [NSSet setWithObject:@"audioController.inputAudioDescription"]; 47 | } 48 | 49 | - (id)initWithAudioController:(AEAudioController*)audioController { 50 | if ( !(self = [super init]) ) return nil; 51 | TPCircularBufferInit(&_buffer, kAudioBufferLength); 52 | self.audioController = audioController; 53 | _volume = 1.0; 54 | return self; 55 | } 56 | 57 | - (void)dealloc { 58 | TPCircularBufferCleanup(&_buffer); 59 | self.audioController = nil; 60 | } 61 | 62 | -(void)setAudioController:(AEAudioController *)audioController { 63 | if ( _audioController ) { 64 | [_audioController removeObserver:self forKeyPath:@"audiobusReceiverPort.connectedToSelf"]; 65 | } 66 | 67 | _audioController = audioController; 68 | 69 | if ( _audioController ) { 70 | [_audioController addObserver:self forKeyPath:@"audiobusReceiverPort.connectedToSelf" options:0 context:(void*)&kAudiobusReceiverPortConnectedToSelfChanged]; 71 | [self updateAudiobusConnectedToSelf]; 72 | } 73 | } 74 | 75 | static void inputCallback(__unsafe_unretained AEPlaythroughChannel *THIS, 76 | __unsafe_unretained AEAudioController *audioController, 77 | void *source, 78 | const AudioTimeStamp *time, 79 | UInt32 frames, 80 | AudioBufferList *audio) { 81 | 82 | if ( THIS->_audiobusConnectedToSelf ) return; 83 | TPCircularBufferCopyAudioBufferList(&THIS->_buffer, audio, time, kTPCircularBufferCopyAll, NULL); 84 | } 85 | 86 | -(AEAudioControllerAudioCallback)receiverCallback { 87 | return inputCallback; 88 | } 89 | 90 | static OSStatus renderCallback(__unsafe_unretained AEPlaythroughChannel *THIS, 91 | __unsafe_unretained AEAudioController *audioController, 92 | const AudioTimeStamp *time, 93 | UInt32 frames, 94 | AudioBufferList *audio) { 95 | while ( 1 ) { 96 | // Discard any buffers with an incompatible format, in the event of a format change 97 | AudioBufferList *nextBuffer = TPCircularBufferNextBufferList(&THIS->_buffer, NULL); 98 | if ( !nextBuffer ) break; 99 | if ( nextBuffer->mNumberBuffers == audio->mNumberBuffers ) break; 100 | TPCircularBufferConsumeNextBufferList(&THIS->_buffer); 101 | } 102 | 103 | UInt32 fillCount = TPCircularBufferPeek(&THIS->_buffer, NULL, AEAudioControllerAudioDescription(audioController)); 104 | if ( fillCount > frames ) { 105 | UInt32 skip = fillCount - frames; 106 | TPCircularBufferDequeueBufferListFrames(&THIS->_buffer, 107 | &skip, 108 | NULL, 109 | NULL, 110 | AEAudioControllerAudioDescription(audioController)); 111 | } 112 | 113 | TPCircularBufferDequeueBufferListFrames(&THIS->_buffer, 114 | &frames, 115 | audio, 116 | NULL, 117 | AEAudioControllerAudioDescription(audioController)); 118 | 119 | return noErr; 120 | } 121 | 122 | -(AEAudioControllerRenderCallback)renderCallback { 123 | return renderCallback; 124 | } 125 | 126 | -(AudioStreamBasicDescription)audioDescription { 127 | return _audioController.inputAudioDescription; 128 | } 129 | 130 | -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 131 | if ( context == &kAudiobusReceiverPortConnectedToSelfChanged ) { 132 | [self updateAudiobusConnectedToSelf]; 133 | } else { 134 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 135 | } 136 | } 137 | 138 | -(void)updateAudiobusConnectedToSelf { 139 | if ( _audioController.audiobusReceiverPort 140 | && [(id)_audioController.audiobusReceiverPort respondsToSelector:@selector(connectedToSelf)] 141 | && [(id)_audioController.audiobusReceiverPort respondsToSelector:@selector(setAutomaticMonitoring:)] ) { 142 | // Handle loopback connections: Pass monitoring responsibilities over to Audiobus SDK, and prepare to mute our own input 143 | _audiobusConnectedToSelf = [(id)_audioController.audiobusReceiverPort connectedToSelf]; 144 | [(id)_audioController.audiobusReceiverPort setAutomaticMonitoring:_audiobusConnectedToSelf]; 145 | } 146 | } 147 | 148 | @end 149 | 150 | 151 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockScheduler.h: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockScheduler.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 22/03/2013. 6 | // Copyright (c) 2013 A Tasty Pixel. All rights reserved. 7 | // 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #import 14 | #import "AEAudioController.h" 15 | 16 | /*! 17 | * Schedule information dictionary keys 18 | */ 19 | extern NSString const * AEBlockSchedulerKeyBlock; 20 | extern NSString const * AEBlockSchedulerKeyTimestampInHostTicks; 21 | extern NSString const * AEBlockSchedulerKeyResponseBlock; 22 | extern NSString const * AEBlockSchedulerKeyIdentifier; 23 | extern NSString const * AEBlockSchedulerKeyTimingContext; 24 | 25 | /*! 26 | * Scheduler block format 27 | * 28 | * Will be executed in a Core Audio thread context, so it's very important not to call 29 | * any Objective-C methods, allocate or free memory, or hold locks. 30 | * 31 | * @param intervalStartTime The timestamp corresponding to the start of this time interval 32 | * @param offsetInFrames The offset, in frames, of this schedule's fire timestamp into the current time interval 33 | */ 34 | typedef void (^AEBlockSchedulerBlock)(const AudioTimeStamp *intervalStartTime, UInt32 offsetInFrames); 35 | 36 | /*! 37 | * Scheduler response block 38 | * 39 | * Will be called on the main thread 40 | */ 41 | typedef void (^AEBlockSchedulerResponseBlock)(); 42 | 43 | /*! 44 | * Block scheduler 45 | * 46 | * This class allows you to schedule blocks to be performed at 47 | * a particular time, on the Core Audio thread. 48 | * 49 | * To use this class, create an instance, then add it as a timing 50 | * receiver using AEAudioController's @link AEAudioController::addTimingReceiver: addTimingReceiver: @endlink. 51 | * 52 | * Then begin scheduling blocks using @link scheduleBlock:atTime:timingContext:identifier: @endlink. 53 | */ 54 | @interface AEBlockScheduler : NSObject 55 | 56 | /*! 57 | * Utility: Get current time 58 | */ 59 | + (uint64_t)now; 60 | 61 | /*! 62 | * Utility: Convert time in seconds to host ticks 63 | */ 64 | + (uint64_t)hostTicksFromSeconds:(NSTimeInterval)seconds; 65 | 66 | /*! 67 | * Utility: Convert time in host ticks to seconds 68 | */ 69 | + (NSTimeInterval)secondsFromHostTicks:(uint64_t)ticks; 70 | 71 | /*! 72 | * Utility: Create a timestamp in host ticks the given number of seconds in the future 73 | */ 74 | + (uint64_t)timestampWithSecondsFromNow:(NSTimeInterval)seconds; 75 | 76 | /*! 77 | * Utility: Create a timestamp in host ticks the given number of seconds from a timestamp 78 | */ 79 | + (uint64_t)timestampWithSeconds:(NSTimeInterval)seconds fromTimestamp:(uint64_t)timeStamp; 80 | 81 | /*! 82 | * Utility: Determine the number of seconds until a given timestamp 83 | */ 84 | + (NSTimeInterval)secondsUntilTimestamp:(uint64_t)timestamp; 85 | 86 | /*! 87 | * Initialize 88 | * 89 | * @param audioController The audio controller 90 | */ 91 | - (id)initWithAudioController:(AEAudioController*)audioController; 92 | 93 | /*! 94 | * Schedule a block for execution 95 | * 96 | * Once scheduled, the given block will be performed at or before the given 97 | * time. Depending on the [hardware buffer duration](@ref AEAudioController::preferredBufferDuration), 98 | * this may occur some milliseconds before the scheduled time. 99 | * 100 | * The actual time corresponding to the beginning of the time interval in which the 101 | * scheduled block was actually invoked will be passed to the block as an argument, as well 102 | * as the number of frames into the time interval that the block is scheduled. 103 | * 104 | * Blocks that are to be performed during the same time interval will be performed in the 105 | * order in which they were scheduled. 106 | * 107 | * VERY IMPORTANT NOTE: This block will be invoked on the Core Audio thread. You must never 108 | * call any Objective-C methods, allocate or free memory, or hold locks within this block, 109 | * or you will cause audio glitches to occur. 110 | * 111 | * @param block Block to perform 112 | * @param time Time at which block will be performed, in host ticks 113 | * @param context Timing context 114 | * @param identifier An identifier used to refer to the schedule later, if necessary (may not be nil) 115 | */ 116 | - (void)scheduleBlock:(AEBlockSchedulerBlock)block atTime:(uint64_t)time timingContext:(AEAudioTimingContext)context identifier:(id)identifier; 117 | 118 | /*! 119 | * Schedule a block for execution, with a response block to be performed on the main thread 120 | * 121 | * Once scheduled, the given block will be performed at or before the given 122 | * time. Depending on the [hardware buffer duration](@ref AEAudioController::preferredBufferDuration), 123 | * this may occur some milliseconds before the scheduled time. 124 | * 125 | * The actual time corresponding to the beginning of the time interval in which the 126 | * scheduled block was actually invoked will be passed to the block as an argument, as well 127 | * as the number of frames into the time interval that the block is scheduled. 128 | * 129 | * Blocks that are to be performed during the same time interval will be performed in the 130 | * order in which they were scheduled. 131 | * 132 | * VERY IMPORTANT NOTE: This block will be invoked on the Core Audio thread. You must never 133 | * call any Objective-C methods, allocate or free memory, or hold locks within this block, 134 | * or you will cause audio glitches to occur. 135 | * 136 | * Once the schedule has finished, the response block will be performed on the main thread. 137 | * 138 | * @param block Block to perform 139 | * @param time Time at which block will be performed, in host ticks 140 | * @param context Timing context 141 | * @param identifier An identifier used to refer to the schedule later, if necessary (may not be nil) 142 | * @param response A block to be performed on the main thread after the main block has been performed 143 | */ 144 | - (void)scheduleBlock:(AEBlockSchedulerBlock)block atTime:(uint64_t)time timingContext:(AEAudioTimingContext)context identifier:(id)identifier mainThreadResponseBlock:(AEBlockSchedulerResponseBlock)response; 145 | 146 | /*! 147 | * Obtain a list of schedules awaiting execution 148 | * 149 | * This will return an array of schedule identifiers, which you passed 150 | * as the 'identifier' parameter when scheduling. 151 | * 152 | * @returns Array of block identifiers 153 | */ 154 | - (NSArray*)schedules; 155 | 156 | /*! 157 | * Obtain information about a particular schedule 158 | * 159 | * This will return a dictionary with information about the schedule associated 160 | * with the given identifier. 161 | */ 162 | - (NSDictionary*)infoForScheduleWithIdentifier:(id)identifier; 163 | 164 | /*! 165 | * Cancel a given schedule, so that it will not be performed 166 | * 167 | * Note: If you have scheduled multiple blocks with the same identifier, 168 | * all of these blocks will be cancelled. 169 | * 170 | * @param identifier The schedule identifier 171 | */ 172 | - (void)cancelScheduleWithIdentifier:(id)identifier; 173 | 174 | @end 175 | 176 | #ifdef __cplusplus 177 | } 178 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioFilePlayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioFilePlayer.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Michael Tyson on 13/02/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AEAudioFilePlayer.h" 27 | #import "AEAudioFileLoaderOperation.h" 28 | #import 29 | 30 | #define checkStatus(status) \ 31 | if ( (status) != noErr ) {\ 32 | NSLog(@"Error: %ld -> %s:%d", (status), __FILE__, __LINE__);\ 33 | } 34 | 35 | @interface AEAudioFilePlayer () { 36 | AudioBufferList *_audio; 37 | UInt32 _lengthInFrames; 38 | AudioStreamBasicDescription _audioDescription; 39 | volatile int32_t _playhead; 40 | } 41 | @property (nonatomic, strong, readwrite) NSURL *url; 42 | @end 43 | 44 | @implementation AEAudioFilePlayer 45 | @synthesize url = _url, loop=_loop, volume=_volume, pan=_pan, channelIsPlaying=_channelIsPlaying, channelIsMuted=_channelIsMuted, removeUponFinish=_removeUponFinish, completionBlock = _completionBlock, startLoopBlock = _startLoopBlock; 46 | @dynamic duration, currentTime; 47 | 48 | + (id)audioFilePlayerWithURL:(NSURL*)url audioController:(AEAudioController *)audioController error:(NSError **)error { 49 | 50 | AEAudioFilePlayer *player = [[self alloc] init]; 51 | player->_volume = 1.0; 52 | player->_channelIsPlaying = YES; 53 | player->_audioDescription = audioController.audioDescription; 54 | player.url = url; 55 | 56 | AEAudioFileLoaderOperation *operation = [[AEAudioFileLoaderOperation alloc] initWithFileURL:url targetAudioDescription:player->_audioDescription]; 57 | [operation start]; 58 | 59 | if ( operation.error ) { 60 | if ( error ) { 61 | *error = operation.error; 62 | } 63 | return nil; 64 | } 65 | 66 | player->_audio = operation.bufferList; 67 | player->_lengthInFrames = operation.lengthInFrames; 68 | 69 | 70 | return player; 71 | } 72 | 73 | - (void)dealloc { 74 | if ( _audio ) { 75 | for ( int i=0; i<_audio->mNumberBuffers; i++ ) { 76 | free(_audio->mBuffers[i].mData); 77 | } 78 | free(_audio); 79 | } 80 | } 81 | 82 | -(NSTimeInterval)duration { 83 | return (double)_lengthInFrames / (double)_audioDescription.mSampleRate; 84 | } 85 | 86 | -(NSTimeInterval)currentTime { 87 | return ((double)_playhead / (double)_lengthInFrames) * [self duration]; 88 | } 89 | 90 | -(void)setCurrentTime:(NSTimeInterval)currentTime { 91 | _playhead = (int32_t)((currentTime / [self duration]) * _lengthInFrames) % _lengthInFrames; 92 | } 93 | 94 | static void notifyLoopRestart(AEAudioController *audioController, void *userInfo, int length) { 95 | AEAudioFilePlayer *THIS = (__bridge AEAudioFilePlayer*)*(void**)userInfo; 96 | 97 | if ( THIS.startLoopBlock ) THIS.startLoopBlock(); 98 | } 99 | 100 | static void notifyPlaybackStopped(AEAudioController *audioController, void *userInfo, int length) { 101 | AEAudioFilePlayer *THIS = (__bridge AEAudioFilePlayer*)*(void**)userInfo; 102 | THIS.channelIsPlaying = NO; 103 | 104 | if ( THIS->_removeUponFinish ) { 105 | [audioController removeChannels:@[THIS]]; 106 | } 107 | 108 | if ( THIS.completionBlock ) THIS.completionBlock(); 109 | 110 | THIS->_playhead = 0; 111 | } 112 | 113 | static OSStatus renderCallback(__unsafe_unretained AEAudioFilePlayer *THIS, __unsafe_unretained AEAudioController *audioController, const AudioTimeStamp *time, UInt32 frames, AudioBufferList *audio) { 114 | int32_t playhead = THIS->_playhead; 115 | int32_t originalPlayhead = playhead; 116 | 117 | if ( !THIS->_channelIsPlaying ) return noErr; 118 | 119 | if ( !THIS->_loop && playhead == THIS->_lengthInFrames ) { 120 | // Notify main thread that playback has finished 121 | AEAudioControllerSendAsynchronousMessageToMainThread(audioController, notifyPlaybackStopped, &THIS, sizeof(AEAudioFilePlayer*)); 122 | THIS->_channelIsPlaying = NO; 123 | return noErr; 124 | } 125 | 126 | // Get pointers to each buffer that we can advance 127 | char *audioPtrs[audio->mNumberBuffers]; 128 | for ( int i=0; imNumberBuffers; i++ ) { 129 | audioPtrs[i] = audio->mBuffers[i].mData; 130 | } 131 | 132 | int bytesPerFrame = THIS->_audioDescription.mBytesPerFrame; 133 | int remainingFrames = frames; 134 | 135 | // Copy audio in contiguous chunks, wrapping around if we're looping 136 | while ( remainingFrames > 0 ) { 137 | // The number of frames left before the end of the audio 138 | int framesToCopy = MIN(remainingFrames, THIS->_lengthInFrames - playhead); 139 | 140 | // Fill each buffer with the audio 141 | for ( int i=0; imNumberBuffers; i++ ) { 142 | memcpy(audioPtrs[i], ((char*)THIS->_audio->mBuffers[i].mData) + playhead * bytesPerFrame, framesToCopy * bytesPerFrame); 143 | 144 | // Advance the output buffers 145 | audioPtrs[i] += framesToCopy * bytesPerFrame; 146 | } 147 | 148 | // Advance playhead 149 | remainingFrames -= framesToCopy; 150 | playhead += framesToCopy; 151 | 152 | if ( playhead >= THIS->_lengthInFrames ) { 153 | // Reached the end of the audio - either loop, or stop 154 | if ( THIS->_loop ) { 155 | playhead = 0; 156 | if ( THIS->_startLoopBlock ) { 157 | // Notify main thread that the loop playback has restarted 158 | AEAudioControllerSendAsynchronousMessageToMainThread(audioController, notifyLoopRestart, &THIS, sizeof(AEAudioFilePlayer*)); 159 | } 160 | } else { 161 | // Notify main thread that playback has finished 162 | AEAudioControllerSendAsynchronousMessageToMainThread(audioController, notifyPlaybackStopped, &THIS, sizeof(AEAudioFilePlayer*)); 163 | THIS->_channelIsPlaying = NO; 164 | break; 165 | } 166 | } 167 | } 168 | 169 | OSAtomicCompareAndSwap32(originalPlayhead, playhead, &THIS->_playhead); 170 | 171 | return noErr; 172 | } 173 | 174 | -(AEAudioControllerRenderCallback)renderCallback { 175 | return &renderCallback; 176 | } 177 | 178 | @end 179 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/Modules/AELimiter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AELimiter.h 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 20/04/2012. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #import 31 | #import 32 | 33 | /*! 34 | * Limiter filter 35 | * 36 | * This class implements a lookahead audio limiter. Use it to 37 | * smoothly limit output volume to a particular level. 38 | * 39 | * The audio is delayed by the number of frames indicated by the 40 | * @link attack @endlink property. 41 | * 42 | * This class operates on non-interleaved floating point audio, 43 | * as it is frequently used as part of larger audio processing operations. 44 | * If your audio is not already in this format, you may wish to 45 | * use it in conjunction with @link AEFloatConverter @endlink. 46 | * 47 | * To use this as an @link AEAudioFilter @endlink, see the 48 | * @link AELimiterFilter @endlink class. 49 | */ 50 | @interface AELimiter : NSObject 51 | 52 | /*! 53 | * Init 54 | * 55 | * @param numberOfChannels Number of channels to use 56 | * @param sampleRate Sample rate to use 57 | */ 58 | - (id)initWithNumberOfChannels:(int)numberOfChannels sampleRate:(Float32)sampleRate; 59 | 60 | /*! 61 | * Enqueue audio 62 | * 63 | * Add audio to be processed. 64 | * 65 | * This C function is safe to be used in a Core Audio realtime thread. 66 | * 67 | * @param limiter A pointer to the limiter object. 68 | * @param buffers An array of floating-point arrays containing noninterleaved audio to enqueue. 69 | * @param length The length of the audio, in frames 70 | * @param timestamp The timestamp of the audio, or NULL 71 | * @return YES on success, NO on failure. 72 | */ 73 | BOOL AELimiterEnqueue(AELimiter *limiter, float** buffers, UInt32 length, const AudioTimeStamp *timestamp); 74 | 75 | /*! 76 | * Dequeue audio 77 | * 78 | * Dequeue processed audio. 79 | * 80 | * Note that the audio is delayed by the number of frames indicated by the 81 | * @link attack @endlink property. If at the end of a processing operation 82 | * you wish to dequeue all audio from the limiter, you should use 83 | * @link AELimiterDrain @endlink. 84 | * 85 | * This C function is safe to be used in a Core Audio realtime thread. 86 | * 87 | * @param limiter A pointer to the limiter object. 88 | * @param buffers An array of floating-point arrays to store the dequeued noninterleaved audio. 89 | * @param ioLength On input, the length of the audio to dequeue, in frames; on output, the amount of audio dequeued. 90 | * @param timestamp On output, the timestamp of the next audio, if not NULL. 91 | */ 92 | void AELimiterDequeue(AELimiter *limiter, float** buffers, UInt32 *ioLength, AudioTimeStamp *timestamp); 93 | 94 | /*! 95 | * Query the fill count of the limiter 96 | * 97 | * Use this to determine how many frames can be dequeued. 98 | * 99 | * @param limiter A pointer to the limiter object. 100 | * @param timestamp On output, if not NULL, the timestamp of the next audio frames 101 | * @param trueFillCount On output, if not NULL, the true fill count, including the @link attack @endlink frames held back for the lookahead algorithm. 102 | * @return The number of frames that can be dequeued 103 | */ 104 | UInt32 AELimiterFillCount(AELimiter *limiter, AudioTimeStamp *timestamp, UInt32 *trueFillCount); 105 | 106 | /*! 107 | * Dequeue all audio from the limiter, including those held back for the lookahead algorithm. 108 | * 109 | * During normal operation, the nmuber of frames given by the @link attack @endlink property are 110 | * held back for the lookahead algorithm to function correctly. If you wish to finish audio processing 111 | * and want to recover these frames, then you can use this function to do so. Note that the final 112 | * frames may surpass the set level. 113 | * 114 | * @param limiter A pointer to the limiter object. 115 | * @param buffers An array of floating-point arrays to store the dequeued noninterleaved audio. 116 | * @param ioLength On input, the length of the audio to dequeue, in frames; on output, the amount of audio dequeued. 117 | * @param timestamp On output, the timestamp of the next audio, if not NULL. 118 | */ 119 | void AELimiterDrain(AELimiter *limiter, float** buffers, UInt32 *ioLength, AudioTimeStamp *timestamp); 120 | 121 | /*! 122 | * Reset the buffer, clearing all enqueued audio 123 | * 124 | * @param limiter The limiter object. 125 | */ 126 | void AELimiterReset(AELimiter *limiter); 127 | 128 | /*! 129 | * The hold interval, in frames 130 | * 131 | * This is the length of time the limiter will hold the 132 | * gain, when it is in the active state. 133 | * 134 | * Default: 22050 (0.5s at 44.1kHz) 135 | */ 136 | @property (nonatomic, assign) UInt32 hold; 137 | 138 | /*! 139 | * The attack duration, in frames 140 | * 141 | * This is the amount of time over which the limiter will 142 | * smoothly activate when an audio level greater than the 143 | * set limit is seen. 144 | * 145 | * Note that the limiter will delay the audio by this duration. 146 | * 147 | * Default: 2048 frames (~.046s at 44.1kHz) 148 | */ 149 | @property (nonatomic, assign) UInt32 attack; 150 | 151 | /*! 152 | * The decay duration, in frames 153 | * 154 | * This is the amount of time over which the limiter 155 | * will smoothly deactivate, moving back to a 1.0 gain level, 156 | * once the hold time expires. 157 | * 158 | * Default: 44100 (1s at 44.1kHz) 159 | */ 160 | @property (nonatomic, assign) UInt32 decay; 161 | 162 | /*! 163 | * The audio level limit 164 | * 165 | * This is the audio level at which the limiter activates. 166 | * The dequeued audio will not exceed this level, and will be 167 | * smoothly gain-adjusted accordingly when a greater level is seen. 168 | * 169 | * The value you provide here will depend on the original audio 170 | * format you are working with. For example, if you are mixing 171 | * a number of 16-bit signed integer streams, you may wish to use 172 | * a limit value of INT16_MAX for the combined stream before 173 | * converting back to 16-bit, to avoid clipping. 174 | * 175 | * Default: INT16_MAX 176 | */ 177 | @property (nonatomic, assign) float level; 178 | 179 | @end 180 | 181 | #ifdef __cplusplus 182 | } 183 | #endif -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/Library/TPCircularBuffer/TPCircularBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // TPCircularBuffer.h 3 | // Circular/Ring buffer implementation 4 | // 5 | // https://github.com/michaeltyson/TPCircularBuffer 6 | // 7 | // Created by Michael Tyson on 10/12/2011. 8 | // 9 | // 10 | // This implementation makes use of a virtual memory mapping technique that inserts a virtual copy 11 | // of the buffer memory directly after the buffer's end, negating the need for any buffer wrap-around 12 | // logic. Clients can simply use the returned memory address as if it were contiguous space. 13 | // 14 | // The implementation is thread-safe in the case of a single producer and single consumer. 15 | // 16 | // Virtual memory technique originally proposed by Philip Howard (http://vrb.slashusr.org/), and 17 | // adapted to Darwin by Kurt Revis (http://www.snoize.com, 18 | // http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz) 19 | // 20 | // 21 | // Copyright (C) 2012-2013 A Tasty Pixel 22 | // 23 | // This software is provided 'as-is', without any express or implied 24 | // warranty. In no event will the authors be held liable for any damages 25 | // arising from the use of this software. 26 | // 27 | // Permission is granted to anyone to use this software for any purpose, 28 | // including commercial applications, and to alter it and redistribute it 29 | // freely, subject to the following restrictions: 30 | // 31 | // 1. The origin of this software must not be misrepresented; you must not 32 | // claim that you wrote the original software. If you use this software 33 | // in a product, an acknowledgment in the product documentation would be 34 | // appreciated but is not required. 35 | // 36 | // 2. Altered source versions must be plainly marked as such, and must not be 37 | // misrepresented as being the original software. 38 | // 39 | // 3. This notice may not be removed or altered from any source distribution. 40 | // 41 | 42 | #ifndef TPCircularBuffer_h 43 | #define TPCircularBuffer_h 44 | 45 | #include 46 | #include 47 | #include 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | typedef struct { 54 | void *buffer; 55 | int32_t length; 56 | int32_t tail; 57 | int32_t head; 58 | volatile int32_t fillCount; 59 | } TPCircularBuffer; 60 | 61 | /*! 62 | * Initialise buffer 63 | * 64 | * Note that the length is advisory only: Because of the way the 65 | * memory mirroring technique works, the true buffer length will 66 | * be multiples of the device page size (e.g. 4096 bytes) 67 | * 68 | * @param buffer Circular buffer 69 | * @param length Length of buffer 70 | */ 71 | bool TPCircularBufferInit(TPCircularBuffer *buffer, int32_t length); 72 | 73 | /*! 74 | * Cleanup buffer 75 | * 76 | * Releases buffer resources. 77 | */ 78 | void TPCircularBufferCleanup(TPCircularBuffer *buffer); 79 | 80 | /*! 81 | * Clear buffer 82 | * 83 | * Resets buffer to original, empty state. 84 | * 85 | * This is safe for use by consumer while producer is accessing 86 | * buffer. 87 | */ 88 | void TPCircularBufferClear(TPCircularBuffer *buffer); 89 | 90 | // Reading (consuming) 91 | 92 | /*! 93 | * Access end of buffer 94 | * 95 | * This gives you a pointer to the end of the buffer, ready 96 | * for reading, and the number of available bytes to read. 97 | * 98 | * @param buffer Circular buffer 99 | * @param availableBytes On output, the number of bytes ready for reading 100 | * @return Pointer to the first bytes ready for reading, or NULL if buffer is empty 101 | */ 102 | static __inline__ __attribute__((always_inline)) void* TPCircularBufferTail(TPCircularBuffer *buffer, int32_t* availableBytes) { 103 | *availableBytes = buffer->fillCount; 104 | if ( *availableBytes == 0 ) return NULL; 105 | return (void*)((char*)buffer->buffer + buffer->tail); 106 | } 107 | 108 | /*! 109 | * Consume bytes in buffer 110 | * 111 | * This frees up the just-read bytes, ready for writing again. 112 | * 113 | * @param buffer Circular buffer 114 | * @param amount Number of bytes to consume 115 | */ 116 | static __inline__ __attribute__((always_inline)) void TPCircularBufferConsume(TPCircularBuffer *buffer, int32_t amount) { 117 | buffer->tail = (buffer->tail + amount) % buffer->length; 118 | OSAtomicAdd32Barrier(-amount, &buffer->fillCount); 119 | assert(buffer->fillCount >= 0); 120 | } 121 | 122 | /*! 123 | * Version of TPCircularBufferConsume without the memory barrier, for more optimal use in single-threaded contexts 124 | */ 125 | static __inline__ __attribute__((always_inline)) void TPCircularBufferConsumeNoBarrier(TPCircularBuffer *buffer, int32_t amount) { 126 | buffer->tail = (buffer->tail + amount) % buffer->length; 127 | buffer->fillCount -= amount; 128 | assert(buffer->fillCount >= 0); 129 | } 130 | 131 | /*! 132 | * Access front of buffer 133 | * 134 | * This gives you a pointer to the front of the buffer, ready 135 | * for writing, and the number of available bytes to write. 136 | * 137 | * @param buffer Circular buffer 138 | * @param availableBytes On output, the number of bytes ready for writing 139 | * @return Pointer to the first bytes ready for writing, or NULL if buffer is full 140 | */ 141 | static __inline__ __attribute__((always_inline)) void* TPCircularBufferHead(TPCircularBuffer *buffer, int32_t* availableBytes) { 142 | *availableBytes = (buffer->length - buffer->fillCount); 143 | if ( *availableBytes == 0 ) return NULL; 144 | return (void*)((char*)buffer->buffer + buffer->head); 145 | } 146 | 147 | // Writing (producing) 148 | 149 | /*! 150 | * Produce bytes in buffer 151 | * 152 | * This marks the given section of the buffer ready for reading. 153 | * 154 | * @param buffer Circular buffer 155 | * @param amount Number of bytes to produce 156 | */ 157 | static __inline__ __attribute__((always_inline)) void TPCircularBufferProduce(TPCircularBuffer *buffer, int amount) { 158 | buffer->head = (buffer->head + amount) % buffer->length; 159 | OSAtomicAdd32Barrier(amount, &buffer->fillCount); 160 | assert(buffer->fillCount <= buffer->length); 161 | } 162 | 163 | /*! 164 | * Version of TPCircularBufferProduce without the memory barrier, for more optimal use in single-threaded contexts 165 | */ 166 | static __inline__ __attribute__((always_inline)) void TPCircularBufferProduceNoBarrier(TPCircularBuffer *buffer, int amount) { 167 | buffer->head = (buffer->head + amount) % buffer->length; 168 | buffer->fillCount += amount; 169 | assert(buffer->fillCount <= buffer->length); 170 | } 171 | 172 | /*! 173 | * Helper routine to copy bytes to buffer 174 | * 175 | * This copies the given bytes to the buffer, and marks them ready for writing. 176 | * 177 | * @param buffer Circular buffer 178 | * @param src Source buffer 179 | * @param len Number of bytes in source buffer 180 | * @return true if bytes copied, false if there was insufficient space 181 | */ 182 | static __inline__ __attribute__((always_inline)) bool TPCircularBufferProduceBytes(TPCircularBuffer *buffer, const void* src, int32_t len) { 183 | int32_t space; 184 | void *ptr = TPCircularBufferHead(buffer, &space); 185 | if ( space < len ) return false; 186 | memcpy(ptr, src, len); 187 | TPCircularBufferProduce(buffer, len); 188 | return true; 189 | } 190 | 191 | #ifdef __cplusplus 192 | } 193 | #endif 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEAudioUnitChannel.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEAudioUnitChannel.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 01/02/2013. 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would be 18 | // appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not be 21 | // misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source distribution. 24 | // 25 | 26 | #import "AEAudioUnitChannel.h" 27 | 28 | #define checkResult(result,operation) (_checkResult((result),(operation),strrchr(__FILE__, '/')+1,__LINE__)) 29 | static inline BOOL _checkResult(OSStatus result, const char *operation, const char* file, int line) { 30 | if ( result != noErr ) { 31 | int fourCC = CFSwapInt32HostToBig(result); 32 | NSLog(@"%s:%d: %s result %d %08X %4.4s\n", file, line, operation, (int)result, (int)result, (char*)&fourCC); 33 | return NO; 34 | } 35 | return YES; 36 | } 37 | 38 | @interface AEAudioUnitChannel () { 39 | AEAudioController *_audioController; 40 | AudioComponentDescription _componentDescription; 41 | AUNode _node; 42 | AudioUnit _audioUnit; 43 | AUNode _converterNode; 44 | AudioUnit _converterUnit; 45 | AUGraph _audioGraph; 46 | } 47 | @end 48 | 49 | @implementation AEAudioUnitChannel 50 | 51 | - (id)initWithComponentDescription:(AudioComponentDescription)audioComponentDescription 52 | audioController:(AEAudioController*)audioController 53 | error:(NSError**)error { 54 | return [self initWithComponentDescription:audioComponentDescription audioController:audioController preInitializeBlock:nil error:error]; 55 | } 56 | 57 | - (id)initWithComponentDescription:(AudioComponentDescription)audioComponentDescription 58 | audioController:(AEAudioController*)audioController 59 | preInitializeBlock:(void(^)(AudioUnit audioUnit))block 60 | error:(NSError**)error { 61 | 62 | if ( !(self = [super init]) ) return nil; 63 | 64 | // Create the node, and the audio unit 65 | _audioController = audioController; 66 | _componentDescription = audioComponentDescription; 67 | _audioGraph = _audioController.audioGraph; 68 | 69 | if ( ![self setup:block error:error] ) { 70 | return nil; 71 | } 72 | 73 | self.volume = 1.0; 74 | self.pan = 0.0; 75 | self.channelIsMuted = NO; 76 | self.channelIsPlaying = YES; 77 | 78 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRecreateGraph:) name:AEAudioControllerDidRecreateGraphNotification object:_audioController]; 79 | 80 | return self; 81 | } 82 | 83 | - (BOOL)setup:(void(^)(AudioUnit audioUnit))block error:(NSError**)error { 84 | OSStatus result; 85 | if ( !checkResult(result=AUGraphAddNode(_audioGraph, &_componentDescription, &_node), "AUGraphAddNode") || 86 | !checkResult(result=AUGraphNodeInfo(_audioGraph, _node, NULL, &_audioUnit), "AUGraphNodeInfo") ) { 87 | if ( error ) *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:result userInfo:@{NSLocalizedDescriptionKey: @"Couldn't initialise audio unit"}]; 88 | return NO; 89 | } 90 | 91 | UInt32 maxFPS = 4096; 92 | checkResult(result=AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, sizeof(maxFPS)), "kAudioUnitProperty_MaximumFramesPerSlice"); 93 | 94 | // Try to set the output audio description 95 | AudioStreamBasicDescription audioDescription = _audioController.audioDescription; 96 | result = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &audioDescription, sizeof(AudioStreamBasicDescription)); 97 | if ( result == kAudioUnitErr_FormatNotSupported ) { 98 | // The audio description isn't supported. Assign modified default audio description, and create an audio converter. 99 | AudioStreamBasicDescription defaultAudioDescription; 100 | UInt32 size = sizeof(defaultAudioDescription); 101 | AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &defaultAudioDescription, &size); 102 | defaultAudioDescription.mSampleRate = audioDescription.mSampleRate; 103 | AEAudioStreamBasicDescriptionSetChannelsPerFrame(&defaultAudioDescription, audioDescription.mChannelsPerFrame); 104 | if ( !checkResult(result=AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &defaultAudioDescription, size), "AudioUnitSetProperty") ) { 105 | if ( error ) *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:result userInfo:@{NSLocalizedDescriptionKey: @"Incompatible audio format"}]; 106 | return NO; 107 | } 108 | 109 | AudioComponentDescription audioConverterDescription = AEAudioComponentDescriptionMake(kAudioUnitManufacturer_Apple, kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter); 110 | if ( !checkResult(result=AUGraphAddNode(_audioGraph, &audioConverterDescription, &_converterNode), "AUGraphAddNode") || 111 | !checkResult(result=AUGraphNodeInfo(_audioGraph, _converterNode, NULL, &_converterUnit), "AUGraphNodeInfo") || 112 | !checkResult(result=AudioUnitSetProperty(_converterUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &defaultAudioDescription, sizeof(AudioStreamBasicDescription)), "AudioUnitSetProperty(kAudioUnitProperty_StreamFormat)") || 113 | !checkResult(result=AudioUnitSetProperty(_converterUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &audioDescription, sizeof(AudioStreamBasicDescription)), "AudioUnitSetProperty(kAudioUnitProperty_StreamFormat)") || 114 | !checkResult(result=AudioUnitSetProperty(_converterUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, sizeof(maxFPS)), "kAudioUnitProperty_MaximumFramesPerSlice") || 115 | !checkResult(result=AUGraphConnectNodeInput(_audioGraph, _node, 0, _converterNode, 0), "AUGraphConnectNodeInput") ) { 116 | 117 | if ( error ) *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:result userInfo:@{NSLocalizedDescriptionKey: @"Couldn't setup converter audio unit"}]; 118 | return NO; 119 | } 120 | 121 | // Set the audio unit to handle up to 4096 frames per slice to keep rendering during screen lock 122 | UInt32 maxFPS = 4096; 123 | checkResult(AudioUnitSetProperty(_converterUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, sizeof(maxFPS)), 124 | "AudioUnitSetProperty(kAudioUnitProperty_MaximumFramesPerSlice)"); 125 | } 126 | 127 | checkResult(AUGraphUpdate(_audioGraph, NULL), "AUGraphUpdate"); 128 | 129 | if(block) block(_audioUnit); 130 | 131 | checkResult(AudioUnitInitialize(_audioUnit), "AudioUnitInitialize"); 132 | 133 | if ( _converterUnit ) { 134 | checkResult(AudioUnitInitialize(_converterUnit), "AudioUnitInitialize"); 135 | } 136 | 137 | return YES; 138 | } 139 | 140 | -(void)dealloc { 141 | [[NSNotificationCenter defaultCenter] removeObserver:self name:AEAudioControllerDidRecreateGraphNotification object:_audioController]; 142 | 143 | if ( _node ) { 144 | checkResult(AUGraphRemoveNode(_audioGraph, _node), "AUGraphRemoveNode"); 145 | } 146 | if ( _converterNode ) { 147 | checkResult(AUGraphRemoveNode(_audioGraph, _converterNode), "AUGraphRemoveNode"); 148 | } 149 | 150 | checkResult(AUGraphUpdate(_audioGraph, NULL), "AUGraphUpdate"); 151 | 152 | } 153 | 154 | -(AudioUnit)audioUnit { 155 | return _audioUnit; 156 | } 157 | 158 | -(AUNode)audioGraphNode { 159 | return _node; 160 | } 161 | 162 | static OSStatus renderCallback(__unsafe_unretained AEAudioUnitChannel *THIS, 163 | __unsafe_unretained AEAudioController *audioController, 164 | const AudioTimeStamp *time, 165 | UInt32 frames, 166 | AudioBufferList *audio) { 167 | AudioUnitRenderActionFlags flags = 0; 168 | checkResult(AudioUnitRender(THIS->_converterUnit ? THIS->_converterUnit : THIS->_audioUnit, &flags, time, 0, frames, audio), "AudioUnitRender"); 169 | return noErr; 170 | } 171 | 172 | -(AEAudioControllerRenderCallback)renderCallback { 173 | return renderCallback; 174 | } 175 | 176 | - (void)didRecreateGraph:(NSNotification*)notification { 177 | _node = 0; 178 | _audioUnit = NULL; 179 | _converterNode = 0; 180 | _converterUnit = NULL; 181 | _audioGraph = _audioController.audioGraph; 182 | [self setup:nil error:NULL]; 183 | } 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /Pods/TheAmazingAudioEngine/TheAmazingAudioEngine/AEBlockScheduler.m: -------------------------------------------------------------------------------- 1 | // 2 | // AEBlockScheduler.m 3 | // TheAmazingAudioEngine 4 | // 5 | // Created by Michael Tyson on 22/03/2013. 6 | // Copyright (c) 2013 A Tasty Pixel. All rights reserved. 7 | // 8 | 9 | #import "AEBlockScheduler.h" 10 | #import 11 | #import 12 | 13 | static double __hostTicksToSeconds = 0.0; 14 | static double __secondsToHostTicks = 0.0; 15 | 16 | const int kMaximumSchedules = 100; 17 | 18 | NSString const * AEBlockSchedulerKeyBlock = @"block"; 19 | NSString const * AEBlockSchedulerKeyTimestampInHostTicks = @"time"; 20 | NSString const * AEBlockSchedulerKeyResponseBlock = @"response"; 21 | NSString const * AEBlockSchedulerKeyIdentifier = @"identifier"; 22 | NSString const * AEBlockSchedulerKeyTimingContext = @"context"; 23 | 24 | struct _schedule_t { 25 | void *block; 26 | void *responseBlock; 27 | uint64_t time; 28 | AEAudioTimingContext context; 29 | void *identifier; 30 | }; 31 | 32 | @interface AEBlockScheduler () { 33 | struct _schedule_t _schedule[kMaximumSchedules]; 34 | int _head; 35 | int _tail; 36 | } 37 | @property (nonatomic, strong) NSMutableArray *scheduledIdentifiers; 38 | @property (nonatomic, weak) AEAudioController *audioController; 39 | @end 40 | 41 | @implementation AEBlockScheduler 42 | @synthesize scheduledIdentifiers = _scheduledIdentifiers; 43 | 44 | +(void)initialize { 45 | mach_timebase_info_data_t tinfo; 46 | mach_timebase_info(&tinfo); 47 | __hostTicksToSeconds = ((double)tinfo.numer / tinfo.denom) * 1.0e-9; 48 | __secondsToHostTicks = 1.0 / __hostTicksToSeconds; 49 | } 50 | 51 | + (uint64_t)now { 52 | return mach_absolute_time(); 53 | } 54 | 55 | + (uint64_t)hostTicksFromSeconds:(NSTimeInterval)seconds { 56 | return seconds * __secondsToHostTicks; 57 | } 58 | 59 | + (NSTimeInterval)secondsFromHostTicks:(uint64_t)ticks { 60 | return (double)ticks * __hostTicksToSeconds; 61 | } 62 | 63 | + (uint64_t)timestampWithSecondsFromNow:(NSTimeInterval)seconds { 64 | return mach_absolute_time() + (seconds * __secondsToHostTicks); 65 | } 66 | 67 | + (NSTimeInterval)secondsUntilTimestamp:(uint64_t)timestamp { 68 | return (int64_t)(timestamp - mach_absolute_time()) * __hostTicksToSeconds; 69 | } 70 | 71 | + (uint64_t)timestampWithSeconds:(NSTimeInterval)seconds fromTimestamp:(uint64_t)timeStamp 72 | { 73 | return (timeStamp + (seconds * __secondsToHostTicks)); 74 | } 75 | 76 | - (id)initWithAudioController:(AEAudioController *)audioController { 77 | if ( !(self = [super init]) ) return nil; 78 | 79 | self.audioController = audioController; 80 | self.scheduledIdentifiers = [NSMutableArray array]; 81 | 82 | return self; 83 | } 84 | 85 | -(void)dealloc { 86 | for ( int i=0; i)identifier { 99 | [self scheduleBlock:block atTime:time timingContext:context identifier:identifier mainThreadResponseBlock:nil]; 100 | } 101 | 102 | -(void)scheduleBlock:(AEBlockSchedulerBlock)block atTime:(uint64_t)time timingContext:(AEAudioTimingContext)context identifier:(id)identifier mainThreadResponseBlock:(AEBlockSchedulerResponseBlock)response { 103 | NSAssert(identifier != nil && block != nil, @"Identifier and block must not be nil"); 104 | 105 | if ( (_head+1)%kMaximumSchedules == _tail ) { 106 | NSLog(@"Unable to schedule block %@: No space in scheduling table.", identifier); 107 | return; 108 | } 109 | 110 | struct _schedule_t *schedule = &_schedule[_head]; 111 | 112 | schedule->identifier = (__bridge_retained void*)[(NSObject*)identifier copy]; 113 | schedule->block = (__bridge_retained void*)[block copy]; 114 | schedule->responseBlock = response ? (__bridge_retained void*)[response copy] : NULL; 115 | schedule->time = time; 116 | schedule->context = context; 117 | 118 | OSMemoryBarrier(); 119 | 120 | _head = (_head+1) % kMaximumSchedules; 121 | [_scheduledIdentifiers addObject:identifier]; 122 | } 123 | 124 | -(NSArray *)schedules { 125 | return _scheduledIdentifiers; 126 | } 127 | 128 | -(void)cancelScheduleWithIdentifier:(id)identifier { 129 | NSAssert(identifier != nil, @"Identifier must not be nil"); 130 | 131 | struct _schedule_t *pointers[kMaximumSchedules]; 132 | struct _schedule_t values[kMaximumSchedules]; 133 | int scheduleCount = 0; 134 | 135 | for ( int i=_tail; i != _head; i=(i+1)%kMaximumSchedules ) { 136 | if ( _schedule[i].identifier && [((__bridge id)_schedule[i].identifier) isEqual:identifier] ) { 137 | pointers[scheduleCount] = &_schedule[i]; 138 | values[scheduleCount] = _schedule[i]; 139 | scheduleCount++; 140 | } 141 | } 142 | 143 | if ( scheduleCount == 0 ) return; 144 | 145 | struct _schedule_t **pointers_array = pointers; 146 | [_audioController performSynchronousMessageExchangeWithBlock:^{ 147 | for ( int i=0; i)identifier { 169 | struct _schedule_t *schedule = [self scheduleWithIdentifier:identifier]; 170 | if ( !schedule ) return nil; 171 | 172 | return @{AEBlockSchedulerKeyBlock: (__bridge id)schedule->block, 173 | AEBlockSchedulerKeyIdentifier: (__bridge id)schedule->identifier, 174 | AEBlockSchedulerKeyResponseBlock: schedule->responseBlock ? (__bridge id)schedule->responseBlock : [NSNull null], 175 | AEBlockSchedulerKeyTimestampInHostTicks: @((long long)schedule->time), 176 | AEBlockSchedulerKeyTimingContext: @((int)schedule->context)}; 177 | } 178 | 179 | - (struct _schedule_t*)scheduleWithIdentifier:(id)identifier { 180 | for ( int i=_tail; i != _head; i=(i+1)%kMaximumSchedules ) { 181 | if ( (identifier && _schedule[i].identifier && [((__bridge id)_schedule[i].identifier) isEqual:identifier]) ) { 182 | return &_schedule[i]; 183 | } 184 | } 185 | return NULL; 186 | } 187 | 188 | struct _timingReceiverFinishSchedule_t { struct _schedule_t schedule; void *THIS; }; 189 | static void timingReceiverFinishSchedule(AEAudioController *audioController, void *userInfo, int len) { 190 | struct _timingReceiverFinishSchedule_t *arg = (struct _timingReceiverFinishSchedule_t*)userInfo; 191 | __unsafe_unretained AEBlockScheduler *THIS = (__bridge AEBlockScheduler*)arg->THIS; 192 | 193 | if ( arg->schedule.responseBlock ) { 194 | ((__bridge_transfer void(^)())arg->schedule.responseBlock)(); 195 | } 196 | CFBridgingRelease(arg->schedule.block); 197 | 198 | [THIS->_scheduledIdentifiers removeObject:(__bridge id)arg->schedule.identifier]; 199 | 200 | CFBridgingRelease(arg->schedule.identifier); 201 | } 202 | 203 | static void timingReceiver(__unsafe_unretained AEBlockScheduler *THIS, 204 | __unsafe_unretained AEAudioController *audioController, 205 | const AudioTimeStamp *time, 206 | UInt32 const frames, 207 | AEAudioTimingContext context) { 208 | uint64_t endTime = time->mHostTime + AEConvertFramesToSeconds(audioController, frames)*__secondsToHostTicks; 209 | 210 | for ( int i=THIS->_tail; i != THIS->_head; i=(i+1)%kMaximumSchedules ) { 211 | if ( THIS->_schedule[i].block && THIS->_schedule[i].context == context && THIS->_schedule[i].time && endTime >= THIS->_schedule[i].time ) { 212 | UInt32 offset = THIS->_schedule[i].time > time->mHostTime ? (UInt32)AEConvertSecondsToFrames(audioController, (THIS->_schedule[i].time - time->mHostTime)*__hostTicksToSeconds) : 0; 213 | ((__bridge AEBlockSchedulerBlock)THIS->_schedule[i].block)(time, offset); 214 | AEAudioControllerSendAsynchronousMessageToMainThread(audioController, 215 | timingReceiverFinishSchedule, 216 | &(struct _timingReceiverFinishSchedule_t) { .schedule = THIS->_schedule[i], .THIS = (__bridge void *)THIS }, 217 | sizeof(struct _timingReceiverFinishSchedule_t)); 218 | memset(&THIS->_schedule[i], 0, sizeof(struct _schedule_t)); 219 | if ( i == THIS->_tail ) { 220 | while ( !THIS->_schedule[THIS->_tail].block && THIS->_tail != THIS->_head ) { 221 | THIS->_tail = (THIS->_tail + 1) % kMaximumSchedules; 222 | } 223 | } 224 | } 225 | } 226 | } 227 | 228 | -(AEAudioControllerTimingCallback)timingReceiverCallback { 229 | return timingReceiver; 230 | } 231 | 232 | @end 233 | -------------------------------------------------------------------------------- /ElaborateDemoVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // ElaborateDemoVC.m 3 | // The Amazing Audio Engine 4 | // 5 | // Created by Ariel Elkin on 01/04/2014. 6 | // Copyright (c) 2014 Ariel Elkin. All rights reserved. 7 | // 8 | 9 | #import "ElaborateDemoVC.h" 10 | 11 | #import "AEAudioController.h" 12 | #import "AESequencerChannel.h" 13 | #import "AESequencerBeat.h" 14 | #import "AESequencerChannelSequence.h" 15 | 16 | #import "SequencerButton.h" 17 | 18 | 19 | @import AVFoundation; 20 | 21 | @interface ElaborateDemoVC() 22 | 23 | @end 24 | 25 | @implementation ElaborateDemoVC { 26 | 27 | AEAudioController *audioController; 28 | 29 | AESequencerChannel *kickChannel; 30 | AESequencerChannel *woodblockChannel; 31 | AESequencerChannel *crickChannel; 32 | AESequencerChannel *hihatChannel; 33 | 34 | AEChannelGroupRef _mainChannelGroup; 35 | 36 | IBOutlet UIButton *playPauseButton; 37 | 38 | bool sequencerIsPlaying; 39 | 40 | NSInteger numberOfRows; 41 | NSInteger numberOfColumns; 42 | CGFloat buttonWidth; 43 | CGFloat buttonHeight; 44 | 45 | } 46 | 47 | 48 | #pragma mark - 49 | #pragma mark Setup 50 | 51 | - (void)viewDidAppear:(BOOL)animated { 52 | [super viewDidAppear:animated]; 53 | 54 | [self setupSequencerUI]; 55 | [self setupAudioController]; 56 | [self setupSequencer]; 57 | 58 | [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgressView) userInfo:nil repeats:YES]; 59 | } 60 | 61 | 62 | - (void)setupSequencerUI { 63 | 64 | [_mainVolumeSlider addTarget:self action:@selector(mainVolumeSliderChanged:) forControlEvents:UIControlEventValueChanged]; 65 | [_bpmSlider addTarget:self action:@selector(bpmSliderChanged:) forControlEvents:UIControlEventValueChanged]; 66 | 67 | 68 | UIView *sequencerView = [UIView new]; 69 | sequencerView.backgroundColor = [UIColor purpleColor]; 70 | sequencerView.translatesAutoresizingMaskIntoConstraints = NO; 71 | 72 | [self.view addSubview:sequencerView]; 73 | 74 | NSArray *constraintsH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[sequencerView]-240-|" options:0 metrics:nil views:@{@"sequencerView": sequencerView}]; 75 | [self.view addConstraints:constraintsH]; 76 | 77 | NSArray *constraintsV = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[sequencerView]|" options:0 metrics:nil views:@{@"sequencerView": sequencerView}]; 78 | [self.view addConstraints:constraintsV]; 79 | 80 | 81 | numberOfRows = 4; 82 | numberOfColumns = 16; 83 | buttonWidth = 35; 84 | buttonHeight = 70; 85 | 86 | for( int i = 0; i < numberOfRows; i++) { 87 | 88 | for ( int j = 0 ; j < numberOfColumns; j++ ) { 89 | 90 | SequencerButton *sequencerButton = [SequencerButton buttonWithRow:i column:j]; 91 | sequencerButton.delegate = self; 92 | CGFloat width = buttonWidth; 93 | CGFloat height = buttonHeight; 94 | CGFloat originX = 20 + (j * width) * 1.2; 95 | CGFloat originY = 20 + (i * height) * 1.2; 96 | sequencerButton.frame = CGRectMake(originX, originY, width, height); 97 | 98 | [sequencerView addSubview:sequencerButton]; 99 | } 100 | } 101 | [self.view bringSubviewToFront:self.playheadPositionOfKickSequence]; 102 | } 103 | 104 | 105 | - (void) updateProgressView { 106 | self.playheadPositionOfKickSequence.progress = kickChannel.playheadPosition; 107 | } 108 | 109 | 110 | #pragma mark - 111 | #pragma mark Playback Control 112 | 113 | - (IBAction)togglePlayPause { 114 | 115 | sequencerIsPlaying = !sequencerIsPlaying; 116 | 117 | // Sweep all channels and apply. 118 | NSArray *channels = [self sequencerChannelsInGroup:_mainChannelGroup]; 119 | for(int i = 0; i < channels.count; i++) { 120 | AESequencerChannel *channel = [channels objectAtIndex:i]; 121 | channel.sequenceIsPlaying = sequencerIsPlaying; 122 | } 123 | 124 | // Toggle button. 125 | if(!sequencerIsPlaying) { 126 | [playPauseButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 127 | playPauseButton.backgroundColor = [UIColor orangeColor]; 128 | } 129 | else { 130 | playPauseButton.backgroundColor = [UIColor blackColor]; 131 | [playPauseButton setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal]; 132 | } 133 | } 134 | 135 | - (void)tappedButton:(SequencerButton *)button { 136 | 137 | AESequencerChannel *selectedChannel; 138 | 139 | if (button.row == 0) selectedChannel = kickChannel; 140 | else if (button.row == 1) selectedChannel = woodblockChannel; 141 | else if (button.row == 2) selectedChannel = crickChannel; 142 | else if (button.row == 3) selectedChannel = hihatChannel; 143 | 144 | double onset = (double)button.column / (double)numberOfColumns; 145 | 146 | AESequencerBeat *beat = [AESequencerBeat beatWithOnset:onset]; 147 | 148 | if (button.isActive) { 149 | [selectedChannel.sequence addBeat:beat]; 150 | } 151 | else { 152 | [selectedChannel.sequence removeBeatAtOnset:onset]; 153 | } 154 | NSLog(@"%@", selectedChannel.sequence); 155 | } 156 | 157 | - (void)mainVolumeSliderChanged:(UISlider*)sender { 158 | [audioController setVolume:sender.value forChannelGroup:_mainChannelGroup]; 159 | } 160 | 161 | - (void)bpmSliderChanged:(UISlider*)sender { 162 | // NSLog(@"bpmSliderChanged: %f", sender.value); 163 | 164 | // Update label. 165 | _bpmLabel.text = [NSString stringWithFormat:@"%f", sender.value]; 166 | 167 | // Sweep all channels and apply. 168 | NSArray *channels = [self sequencerChannelsInGroup:_mainChannelGroup]; 169 | for(int i = 0; i < channels.count; i++) { 170 | AESequencerChannel *channel = [channels objectAtIndex:i]; 171 | channel.bpm = sender.value; 172 | } 173 | } 174 | 175 | 176 | #pragma mark - 177 | #pragma mark Sequencer Setup 178 | 179 | - (void)setupSequencer { 180 | _mainChannelGroup = [audioController createChannelGroup]; 181 | sequencerIsPlaying = false; 182 | 183 | 184 | // Pattern vars. 185 | double bpm = _bpmSlider.value; 186 | NSUInteger numBeats = 4; 187 | 188 | // KICK channel 189 | NSURL *kickURL = [[NSBundle mainBundle] URLForResource:@"kick" withExtension:@"caf"]; 190 | AESequencerChannelSequence *kickSequence = [AESequencerChannelSequence new]; 191 | kickChannel = [AESequencerChannel sequencerChannelWithAudioFileAt:kickURL 192 | audioController:audioController 193 | withSequence:kickSequence 194 | numberOfFullBeatsPerMeasure:numBeats 195 | atBPM:bpm]; 196 | [audioController addChannels:@[kickChannel] toChannelGroup:_mainChannelGroup]; 197 | 198 | 199 | // WOODBLOCK channel 200 | NSURL *woodblockURL = [[NSBundle mainBundle] URLForResource:@"woodblock" withExtension:@"caf"]; 201 | AESequencerChannelSequence *woodblockSequence = [AESequencerChannelSequence new]; 202 | woodblockChannel = [AESequencerChannel sequencerChannelWithAudioFileAt:woodblockURL 203 | audioController:audioController 204 | withSequence:woodblockSequence 205 | numberOfFullBeatsPerMeasure:numBeats 206 | atBPM:bpm]; 207 | [audioController addChannels:@[woodblockChannel] toChannelGroup:_mainChannelGroup]; 208 | 209 | 210 | 211 | // CRICK channel 212 | NSURL *crickURL = [[NSBundle mainBundle] URLForResource:@"crick" withExtension:@"caf"]; 213 | AESequencerChannelSequence *crickSequence = [AESequencerChannelSequence new]; 214 | crickChannel = [AESequencerChannel sequencerChannelWithAudioFileAt:crickURL 215 | audioController:audioController 216 | withSequence:crickSequence 217 | numberOfFullBeatsPerMeasure:numBeats 218 | atBPM:bpm]; 219 | [audioController addChannels:@[crickChannel] toChannelGroup:_mainChannelGroup]; 220 | 221 | 222 | // HI-HAT channel 223 | NSURL *hihatURL = [[NSBundle mainBundle] URLForResource:@"hihat" withExtension:@"caf"]; 224 | AESequencerChannelSequence *hihatSequence = [AESequencerChannelSequence new]; 225 | hihatChannel = [AESequencerChannel sequencerChannelWithAudioFileAt:hihatURL 226 | audioController:audioController 227 | withSequence:hihatSequence 228 | numberOfFullBeatsPerMeasure:numBeats 229 | atBPM:bpm]; 230 | [audioController addChannels:@[hihatChannel] toChannelGroup:_mainChannelGroup]; 231 | 232 | } 233 | 234 | - (void)setupAudioController { 235 | 236 | // Init audio controller: 237 | audioController = [[AEAudioController alloc] initWithAudioDescription:[AEAudioController nonInterleavedFloatStereoAudioDescription]]; 238 | 239 | // Start it. 240 | NSError *audioControllerStartError = nil; 241 | [audioController start:&audioControllerStartError]; 242 | if (audioControllerStartError) { 243 | NSLog(@"Audio controller start error: %@", audioControllerStartError.localizedDescription); 244 | } 245 | } 246 | 247 | - (IBAction)pressedBackButton{ 248 | 249 | for (AESequencerChannel *channel in [audioController channelsInChannelGroup:_mainChannelGroup]){ 250 | channel.sequenceIsPlaying = false; 251 | } 252 | [audioController stop]; 253 | [self dismissViewControllerAnimated:YES completion:nil]; 254 | 255 | } 256 | 257 | 258 | #pragma mark - 259 | #pragma mark Utils 260 | 261 | - (NSArray*)sequencerChannelsInGroup:(AEChannelGroupRef)group { 262 | 263 | NSMutableArray *seqChannels = [NSMutableArray array]; 264 | 265 | NSArray *channels = [audioController channelsInChannelGroup:group]; 266 | for(int i = 0; i < channels.count; i++) { 267 | id channel = [channels objectAtIndex:i]; 268 | if([channel isKindOfClass:[AESequencerChannel class]]) { 269 | [seqChannels addObject:channel]; 270 | } 271 | } 272 | 273 | return seqChannels; 274 | } 275 | 276 | @end 277 | 278 | --------------------------------------------------------------------------------