├── PitchDetectorExample.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── kevinmurphy.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── kevinmurphy.xcuserdatad │ └── xcschemes │ ├── PitchDetectorExample.xcscheme │ └── xcschememanagement.plist ├── PitchDetectorExample ├── AppDelegate.h ├── AppDelegate.m ├── AudioController.h ├── AudioController.m ├── FreqViewController.h ├── FreqViewController.m ├── PitchDetector.h ├── PitchDetector.m ├── PitchDetectorExample-Info.plist ├── PitchDetectorExample-Prefix.pch ├── TPCircularBuffer.c ├── TPCircularBuffer.h ├── en.lproj │ └── InfoPlist.strings └── main.m └── README.txt /PitchDetectorExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 101E675A15A511E700FFF744 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 101E675915A511E700FFF744 /* UIKit.framework */; }; 11 | 101E675C15A511E700FFF744 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 101E675B15A511E700FFF744 /* Foundation.framework */; }; 12 | 101E675E15A511E700FFF744 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 101E675D15A511E700FFF744 /* CoreGraphics.framework */; }; 13 | 101E676415A511E700FFF744 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 101E676215A511E700FFF744 /* InfoPlist.strings */; }; 14 | 101E676615A511E700FFF744 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 101E676515A511E700FFF744 /* main.m */; }; 15 | 101E676A15A511E700FFF744 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 101E676915A511E700FFF744 /* AppDelegate.m */; }; 16 | 101E677E15A512A800FFF744 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 101E677C15A512A800FFF744 /* Accelerate.framework */; }; 17 | 101E677F15A512A800FFF744 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 101E677D15A512A800FFF744 /* AudioToolbox.framework */; }; 18 | 101E678815A5163300FFF744 /* AudioController.m in Sources */ = {isa = PBXBuildFile; fileRef = 101E678115A5163300FFF744 /* AudioController.m */; }; 19 | 101E678915A5163300FFF744 /* FreqViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 101E678315A5163300FFF744 /* FreqViewController.m */; }; 20 | 101E678A15A5163300FFF744 /* PitchDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = 101E678515A5163300FFF744 /* PitchDetector.m */; }; 21 | 101E678B15A5163300FFF744 /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 101E678615A5163300FFF744 /* TPCircularBuffer.c */; }; 22 | 101E678D15A5177E00FFF744 /* README.txt in Resources */ = {isa = PBXBuildFile; fileRef = 101E678C15A5177E00FFF744 /* README.txt */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 101E675515A511E700FFF744 /* PitchDetectorExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PitchDetectorExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 101E675915A511E700FFF744 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28 | 101E675B15A511E700FFF744 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 29 | 101E675D15A511E700FFF744 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 30 | 101E676115A511E700FFF744 /* PitchDetectorExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PitchDetectorExample-Info.plist"; sourceTree = ""; }; 31 | 101E676315A511E700FFF744 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 32 | 101E676515A511E700FFF744 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 101E676715A511E700FFF744 /* PitchDetectorExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PitchDetectorExample-Prefix.pch"; sourceTree = ""; }; 34 | 101E676815A511E700FFF744 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | 101E676915A511E700FFF744 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | 101E677C15A512A800FFF744 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 37 | 101E677D15A512A800FFF744 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 38 | 101E678015A5163300FFF744 /* AudioController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioController.h; sourceTree = ""; }; 39 | 101E678115A5163300FFF744 /* AudioController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioController.m; sourceTree = ""; }; 40 | 101E678215A5163300FFF744 /* FreqViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FreqViewController.h; sourceTree = ""; }; 41 | 101E678315A5163300FFF744 /* FreqViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FreqViewController.m; sourceTree = ""; }; 42 | 101E678415A5163300FFF744 /* PitchDetector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PitchDetector.h; sourceTree = ""; }; 43 | 101E678515A5163300FFF744 /* PitchDetector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PitchDetector.m; sourceTree = ""; }; 44 | 101E678615A5163300FFF744 /* TPCircularBuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = TPCircularBuffer.c; sourceTree = ""; }; 45 | 101E678715A5163300FFF744 /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = ""; }; 46 | 101E678C15A5177E00FFF744 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = ../README.txt; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 101E675215A511E700FFF744 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | 101E677E15A512A800FFF744 /* Accelerate.framework in Frameworks */, 55 | 101E677F15A512A800FFF744 /* AudioToolbox.framework in Frameworks */, 56 | 101E675A15A511E700FFF744 /* UIKit.framework in Frameworks */, 57 | 101E675C15A511E700FFF744 /* Foundation.framework in Frameworks */, 58 | 101E675E15A511E700FFF744 /* CoreGraphics.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 101E674A15A511E700FFF744 = { 66 | isa = PBXGroup; 67 | children = ( 68 | 101E675F15A511E700FFF744 /* PitchDetectorExample */, 69 | 101E675815A511E700FFF744 /* Frameworks */, 70 | 101E675615A511E700FFF744 /* Products */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | 101E675615A511E700FFF744 /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 101E675515A511E700FFF744 /* PitchDetectorExample.app */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | 101E675815A511E700FFF744 /* Frameworks */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 101E677C15A512A800FFF744 /* Accelerate.framework */, 86 | 101E677D15A512A800FFF744 /* AudioToolbox.framework */, 87 | 101E675915A511E700FFF744 /* UIKit.framework */, 88 | 101E675B15A511E700FFF744 /* Foundation.framework */, 89 | 101E675D15A511E700FFF744 /* CoreGraphics.framework */, 90 | ); 91 | name = Frameworks; 92 | sourceTree = ""; 93 | }; 94 | 101E675F15A511E700FFF744 /* PitchDetectorExample */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 101E678015A5163300FFF744 /* AudioController.h */, 98 | 101E678115A5163300FFF744 /* AudioController.m */, 99 | 101E678215A5163300FFF744 /* FreqViewController.h */, 100 | 101E678315A5163300FFF744 /* FreqViewController.m */, 101 | 101E678415A5163300FFF744 /* PitchDetector.h */, 102 | 101E678515A5163300FFF744 /* PitchDetector.m */, 103 | 101E678615A5163300FFF744 /* TPCircularBuffer.c */, 104 | 101E678715A5163300FFF744 /* TPCircularBuffer.h */, 105 | 101E676815A511E700FFF744 /* AppDelegate.h */, 106 | 101E676915A511E700FFF744 /* AppDelegate.m */, 107 | 101E676015A511E700FFF744 /* Supporting Files */, 108 | 101E678C15A5177E00FFF744 /* README.txt */, 109 | ); 110 | path = PitchDetectorExample; 111 | sourceTree = ""; 112 | }; 113 | 101E676015A511E700FFF744 /* Supporting Files */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 101E676115A511E700FFF744 /* PitchDetectorExample-Info.plist */, 117 | 101E676215A511E700FFF744 /* InfoPlist.strings */, 118 | 101E676515A511E700FFF744 /* main.m */, 119 | 101E676715A511E700FFF744 /* PitchDetectorExample-Prefix.pch */, 120 | ); 121 | name = "Supporting Files"; 122 | sourceTree = ""; 123 | }; 124 | /* End PBXGroup section */ 125 | 126 | /* Begin PBXNativeTarget section */ 127 | 101E675415A511E700FFF744 /* PitchDetectorExample */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 101E676D15A511E700FFF744 /* Build configuration list for PBXNativeTarget "PitchDetectorExample" */; 130 | buildPhases = ( 131 | 101E675115A511E700FFF744 /* Sources */, 132 | 101E675215A511E700FFF744 /* Frameworks */, 133 | 101E675315A511E700FFF744 /* Resources */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | ); 139 | name = PitchDetectorExample; 140 | productName = PitchDetectorExample; 141 | productReference = 101E675515A511E700FFF744 /* PitchDetectorExample.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | 101E674C15A511E700FFF744 /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | LastUpgradeCheck = 0430; 151 | ORGANIZATIONNAME = "New York University"; 152 | }; 153 | buildConfigurationList = 101E674F15A511E700FFF744 /* Build configuration list for PBXProject "PitchDetectorExample" */; 154 | compatibilityVersion = "Xcode 3.2"; 155 | developmentRegion = English; 156 | hasScannedForEncodings = 0; 157 | knownRegions = ( 158 | en, 159 | ); 160 | mainGroup = 101E674A15A511E700FFF744; 161 | productRefGroup = 101E675615A511E700FFF744 /* Products */; 162 | projectDirPath = ""; 163 | projectRoot = ""; 164 | targets = ( 165 | 101E675415A511E700FFF744 /* PitchDetectorExample */, 166 | ); 167 | }; 168 | /* End PBXProject section */ 169 | 170 | /* Begin PBXResourcesBuildPhase section */ 171 | 101E675315A511E700FFF744 /* Resources */ = { 172 | isa = PBXResourcesBuildPhase; 173 | buildActionMask = 2147483647; 174 | files = ( 175 | 101E676415A511E700FFF744 /* InfoPlist.strings in Resources */, 176 | 101E678D15A5177E00FFF744 /* README.txt in Resources */, 177 | ); 178 | runOnlyForDeploymentPostprocessing = 0; 179 | }; 180 | /* End PBXResourcesBuildPhase section */ 181 | 182 | /* Begin PBXSourcesBuildPhase section */ 183 | 101E675115A511E700FFF744 /* Sources */ = { 184 | isa = PBXSourcesBuildPhase; 185 | buildActionMask = 2147483647; 186 | files = ( 187 | 101E676615A511E700FFF744 /* main.m in Sources */, 188 | 101E676A15A511E700FFF744 /* AppDelegate.m in Sources */, 189 | 101E678815A5163300FFF744 /* AudioController.m in Sources */, 190 | 101E678915A5163300FFF744 /* FreqViewController.m in Sources */, 191 | 101E678A15A5163300FFF744 /* PitchDetector.m in Sources */, 192 | 101E678B15A5163300FFF744 /* TPCircularBuffer.c in Sources */, 193 | ); 194 | runOnlyForDeploymentPostprocessing = 0; 195 | }; 196 | /* End PBXSourcesBuildPhase section */ 197 | 198 | /* Begin PBXVariantGroup section */ 199 | 101E676215A511E700FFF744 /* InfoPlist.strings */ = { 200 | isa = PBXVariantGroup; 201 | children = ( 202 | 101E676315A511E700FFF744 /* en */, 203 | ); 204 | name = InfoPlist.strings; 205 | sourceTree = ""; 206 | }; 207 | /* End PBXVariantGroup section */ 208 | 209 | /* Begin XCBuildConfiguration section */ 210 | 101E676B15A511E700FFF744 /* Debug */ = { 211 | isa = XCBuildConfiguration; 212 | buildSettings = { 213 | ALWAYS_SEARCH_USER_PATHS = NO; 214 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 215 | CLANG_ENABLE_OBJC_ARC = YES; 216 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 217 | COPY_PHASE_STRIP = NO; 218 | GCC_C_LANGUAGE_STANDARD = gnu99; 219 | GCC_DYNAMIC_NO_PIC = NO; 220 | GCC_OPTIMIZATION_LEVEL = 0; 221 | GCC_PREPROCESSOR_DEFINITIONS = ( 222 | "DEBUG=1", 223 | "$(inherited)", 224 | ); 225 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 226 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 227 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 229 | GCC_WARN_UNUSED_VARIABLE = YES; 230 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 231 | SDKROOT = iphoneos; 232 | }; 233 | name = Debug; 234 | }; 235 | 101E676C15A511E700FFF744 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | ALWAYS_SEARCH_USER_PATHS = NO; 239 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 240 | CLANG_ENABLE_OBJC_ARC = YES; 241 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 242 | COPY_PHASE_STRIP = YES; 243 | GCC_C_LANGUAGE_STANDARD = gnu99; 244 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 245 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 247 | GCC_WARN_UNUSED_VARIABLE = YES; 248 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 249 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 250 | SDKROOT = iphoneos; 251 | VALIDATE_PRODUCT = YES; 252 | }; 253 | name = Release; 254 | }; 255 | 101E676E15A511E700FFF744 /* Debug */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 259 | GCC_PREFIX_HEADER = "PitchDetectorExample/PitchDetectorExample-Prefix.pch"; 260 | INFOPLIST_FILE = "PitchDetectorExample/PitchDetectorExample-Info.plist"; 261 | PRODUCT_NAME = "$(TARGET_NAME)"; 262 | WRAPPER_EXTENSION = app; 263 | }; 264 | name = Debug; 265 | }; 266 | 101E676F15A511E700FFF744 /* Release */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 270 | GCC_PREFIX_HEADER = "PitchDetectorExample/PitchDetectorExample-Prefix.pch"; 271 | INFOPLIST_FILE = "PitchDetectorExample/PitchDetectorExample-Info.plist"; 272 | PRODUCT_NAME = "$(TARGET_NAME)"; 273 | WRAPPER_EXTENSION = app; 274 | }; 275 | name = Release; 276 | }; 277 | /* End XCBuildConfiguration section */ 278 | 279 | /* Begin XCConfigurationList section */ 280 | 101E674F15A511E700FFF744 /* Build configuration list for PBXProject "PitchDetectorExample" */ = { 281 | isa = XCConfigurationList; 282 | buildConfigurations = ( 283 | 101E676B15A511E700FFF744 /* Debug */, 284 | 101E676C15A511E700FFF744 /* Release */, 285 | ); 286 | defaultConfigurationIsVisible = 0; 287 | defaultConfigurationName = Release; 288 | }; 289 | 101E676D15A511E700FFF744 /* Build configuration list for PBXNativeTarget "PitchDetectorExample" */ = { 290 | isa = XCConfigurationList; 291 | buildConfigurations = ( 292 | 101E676E15A511E700FFF744 /* Debug */, 293 | 101E676F15A511E700FFF744 /* Release */, 294 | ); 295 | defaultConfigurationIsVisible = 0; 296 | }; 297 | /* End XCConfigurationList section */ 298 | }; 299 | rootObject = 101E674C15A511E700FFF744 /* Project object */; 300 | } 301 | -------------------------------------------------------------------------------- /PitchDetectorExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PitchDetectorExample.xcodeproj/project.xcworkspace/xcuserdata/kevinmurphy.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlypatrick/PitchDetectorExample/9e30a41306eeaeb7d09e929be65564faeac8abf4/PitchDetectorExample.xcodeproj/project.xcworkspace/xcuserdata/kevinmurphy.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PitchDetectorExample.xcodeproj/xcuserdata/kevinmurphy.xcuserdatad/xcschemes/PitchDetectorExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 50 | 51 | 57 | 58 | 59 | 60 | 61 | 62 | 68 | 69 | 75 | 76 | 77 | 78 | 80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /PitchDetectorExample.xcodeproj/xcuserdata/kevinmurphy.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PitchDetectorExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 101E675415A511E700FFF744 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PitchDetectorExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PitchDetectorExample 4 | // 5 | // Created by Kevin Murphy on 7/4/12. 6 | // Copyright (c) 2012 New York University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PitchDetectorExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PitchDetectorExample 4 | // 5 | // Created by Kevin Murphy on 7/4/12. 6 | // Copyright (c) 2012 New York University. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "FreqViewController.h" 11 | 12 | @implementation AppDelegate 13 | 14 | @synthesize window = _window; 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 19 | // Override point for customization after application launch. 20 | self.window.backgroundColor = [UIColor whiteColor]; 21 | self.window.rootViewController = [[FreqViewController alloc] initWithNibName:nil bundle:nil]; 22 | [self.window makeKeyAndVisible]; 23 | return YES; 24 | } 25 | 26 | - (void)applicationWillResignActive:(UIApplication *)application 27 | { 28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 30 | } 31 | 32 | - (void)applicationDidEnterBackground:(UIApplication *)application 33 | { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | - (void)applicationWillEnterForeground:(UIApplication *)application 39 | { 40 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 41 | } 42 | 43 | - (void)applicationDidBecomeActive:(UIApplication *)application 44 | { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | - (void)applicationWillTerminate:(UIApplication *)application 49 | { 50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /PitchDetectorExample/AudioController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) Kevin P Murphy June 2012 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | @protocol AudioControllerDelegate 15 | @required 16 | - (void) receivedAudioSamples:(SInt16*) samples length:(int) len; 17 | @end 18 | 19 | @interface AudioController : NSObject 20 | { 21 | @public 22 | AudioBufferList bufferList; 23 | } 24 | @property (nonatomic, assign) AudioStreamBasicDescription audioFormat; 25 | @property (nonatomic, assign) AudioUnit rioUnit; 26 | @property (nonatomic, assign) id delegate; 27 | 28 | + (AudioController*) sharedAudioManager; 29 | - (void) startAudio; 30 | 31 | 32 | @end 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /PitchDetectorExample/AudioController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) Kevin P Murphy June 2012 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | */ 10 | 11 | #import "AudioController.h" 12 | 13 | #define kOutputBus 0 14 | #define kInputBus 1 15 | 16 | @implementation AudioController 17 | @synthesize rioUnit, audioFormat, delegate; 18 | 19 | 20 | + (AudioController *) sharedAudioManager 21 | { 22 | static AudioController *sharedAudioManager; 23 | 24 | @synchronized(self) 25 | { 26 | if (!sharedAudioManager) { 27 | sharedAudioManager = [[AudioController alloc] init]; 28 | [sharedAudioManager startAudio]; 29 | } 30 | return sharedAudioManager; 31 | } 32 | } 33 | 34 | 35 | void checkStatus(OSStatus status); 36 | void checkStatus(OSStatus status) { 37 | if(status!=0) 38 | printf("Error: %ld\n", status); 39 | } 40 | 41 | #pragma mark init 42 | 43 | - (id)init 44 | { 45 | OSStatus status; 46 | status = AudioSessionInitialize(NULL, NULL, NULL, (__bridge void*) self); 47 | checkStatus(status); 48 | 49 | // Describe audio component 50 | AudioComponentDescription desc; 51 | desc.componentType = kAudioUnitType_Output; 52 | desc.componentSubType = kAudioUnitSubType_RemoteIO; 53 | desc.componentFlags = 0; 54 | desc.componentFlagsMask = 0; 55 | desc.componentManufacturer = kAudioUnitManufacturer_Apple; 56 | 57 | // Get component 58 | AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc); 59 | 60 | // Get audio units 61 | status = AudioComponentInstanceNew(inputComponent, &rioUnit); 62 | checkStatus(status); 63 | 64 | 65 | // Enable IO for recording 66 | UInt32 flag = 1; 67 | 68 | status = AudioUnitSetProperty(rioUnit, 69 | kAudioOutputUnitProperty_EnableIO, 70 | kAudioUnitScope_Input, 71 | kInputBus, 72 | &flag, 73 | sizeof(flag)); 74 | checkStatus(status); 75 | 76 | 77 | // Describe format 78 | audioFormat.mSampleRate= 44100.0; 79 | audioFormat.mFormatID= kAudioFormatLinearPCM; 80 | audioFormat.mFormatFlags= kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 81 | audioFormat.mFramesPerPacket= 1; 82 | audioFormat.mChannelsPerFrame= 1; 83 | audioFormat.mBitsPerChannel= 16; 84 | audioFormat.mBytesPerPacket= 2; 85 | audioFormat.mBytesPerFrame= 2; 86 | 87 | // Apply format 88 | status = AudioUnitSetProperty(rioUnit, 89 | kAudioUnitProperty_StreamFormat, 90 | kAudioUnitScope_Output, 91 | kInputBus, 92 | &audioFormat, 93 | sizeof(audioFormat)); 94 | checkStatus(status); 95 | 96 | status = AudioUnitSetProperty(rioUnit, 97 | kAudioUnitProperty_StreamFormat, 98 | kAudioUnitScope_Input, 99 | kOutputBus, 100 | &audioFormat, 101 | sizeof(audioFormat)); 102 | checkStatus(status); 103 | 104 | // Set input callback 105 | AURenderCallbackStruct callbackStruct; 106 | callbackStruct.inputProc = recordingCallback; 107 | callbackStruct.inputProcRefCon = (__bridge void*)self; 108 | 109 | status = AudioUnitSetProperty(rioUnit, 110 | kAudioOutputUnitProperty_SetInputCallback, 111 | kAudioUnitScope_Global, 112 | kInputBus, 113 | &callbackStruct, 114 | sizeof(callbackStruct)); 115 | checkStatus(status); 116 | 117 | 118 | // Disable buffer allocation for the recorder 119 | flag = 0; 120 | status = AudioUnitSetProperty(rioUnit, kAudioUnitProperty_ShouldAllocateBuffer, kAudioUnitScope_Global, kInputBus, &flag, sizeof(flag)); 121 | 122 | 123 | // Initialise 124 | UInt32 category = kAudioSessionCategory_PlayAndRecord; 125 | status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category); 126 | checkStatus(status); 127 | 128 | status = 0; 129 | status = AudioSessionSetActive(YES); 130 | checkStatus(status); 131 | 132 | status = AudioUnitInitialize(rioUnit); 133 | checkStatus(status); 134 | 135 | return self; 136 | } 137 | 138 | #pragma mark Recording Callback 139 | static OSStatus recordingCallback(void *inRefCon, 140 | AudioUnitRenderActionFlags *ioActionFlags, 141 | const AudioTimeStamp *inTimeStamp, 142 | UInt32 inBusNumber, 143 | UInt32 inNumberFrames, 144 | AudioBufferList *ioData) { 145 | 146 | AudioController *THIS = (__bridge AudioController*) inRefCon; 147 | 148 | THIS->bufferList.mNumberBuffers = 1; 149 | THIS->bufferList.mBuffers[0].mDataByteSize = sizeof(SInt16)*inNumberFrames; 150 | THIS->bufferList.mBuffers[0].mNumberChannels = 1; 151 | THIS->bufferList.mBuffers[0].mData = (SInt16*) malloc(sizeof(SInt16)*inNumberFrames); 152 | 153 | OSStatus status; 154 | 155 | status = AudioUnitRender(THIS->rioUnit, 156 | ioActionFlags, 157 | inTimeStamp, 158 | inBusNumber, 159 | inNumberFrames, 160 | &(THIS->bufferList)); 161 | checkStatus(status); 162 | 163 | dispatch_async(dispatch_get_main_queue(), ^{ 164 | [THIS.delegate receivedAudioSamples:(SInt16*)THIS->bufferList.mBuffers[0].mData length:inNumberFrames]; 165 | }); 166 | 167 | return noErr; 168 | } 169 | 170 | 171 | 172 | -(void) startAudio 173 | { 174 | OSStatus status = AudioOutputUnitStart(rioUnit); 175 | checkStatus(status); 176 | printf("Audio Initialized - sampleRate: %f\n", audioFormat.mSampleRate); 177 | } 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /PitchDetectorExample/FreqViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) Kevin P Murphy June 2012 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | */ 10 | 11 | #import 12 | #import "AudioController.h" 13 | #import "PitchDetector.h" 14 | 15 | @interface FreqViewController : UIViewController 16 | { 17 | UILabel *freqLabel; 18 | AudioController *audioManager; 19 | PitchDetector *autoCorrelator; 20 | 21 | NSMutableArray *medianPitchFollow; 22 | } 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /PitchDetectorExample/FreqViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) Kevin P Murphy June 2012 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | */ 10 | 11 | #import "FreqViewController.h" 12 | 13 | @interface FreqViewController () 14 | 15 | @end 16 | 17 | @implementation FreqViewController 18 | - (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 19 | self = [super initWithNibName:nil bundle:nil]; 20 | 21 | self.view.backgroundColor = [UIColor whiteColor]; 22 | 23 | return self; 24 | 25 | } 26 | 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | audioManager = [AudioController sharedAudioManager]; 32 | audioManager.delegate = self; 33 | autoCorrelator = [[PitchDetector alloc] initWithSampleRate:audioManager.audioFormat.mSampleRate lowBoundFreq:30 hiBoundFreq:4500 andDelegate:self]; 34 | 35 | medianPitchFollow = [[NSMutableArray alloc] initWithCapacity:22]; 36 | 37 | freqLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 80)]; 38 | freqLabel.center = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2); 39 | freqLabel.backgroundColor = [UIColor clearColor]; 40 | freqLabel.textAlignment = UITextAlignmentCenter; 41 | 42 | [self.view addSubview:freqLabel]; 43 | 44 | } 45 | 46 | - (void)viewDidUnload 47 | { 48 | [super viewDidUnload]; 49 | } 50 | 51 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 52 | { 53 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 54 | } 55 | 56 | - (void) updatedPitch:(float)frequency { 57 | 58 | double value = frequency; 59 | 60 | 61 | 62 | //############ DATA SMOOTHING ############### 63 | //### The following code averages previous values ## 64 | //### received by the pitch follower by using a ## 65 | //### median filter. Provides sub cent precision! ## 66 | //############################################# 67 | 68 | NSNumber *nsnum = [NSNumber numberWithDouble:value]; 69 | [medianPitchFollow insertObject:nsnum atIndex:0]; 70 | 71 | if(medianPitchFollow.count>22) { 72 | [medianPitchFollow removeObjectAtIndex:medianPitchFollow.count-1]; 73 | } 74 | double median = 0; 75 | 76 | 77 | 78 | if(medianPitchFollow.count>=2) { 79 | NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO]; 80 | NSMutableArray *tempSort = [NSMutableArray arrayWithArray:medianPitchFollow]; 81 | [tempSort sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]]; 82 | 83 | if(tempSort.count%2==0) { 84 | double first = 0, second = 0; 85 | first = [[tempSort objectAtIndex:tempSort.count/2-1] doubleValue]; 86 | second = [[tempSort objectAtIndex:tempSort.count/2] doubleValue]; 87 | median = (first+second)/2; 88 | value = median; 89 | } else { 90 | median = [[tempSort objectAtIndex:tempSort.count/2] doubleValue]; 91 | value = median; 92 | } 93 | 94 | [tempSort removeAllObjects]; 95 | tempSort = nil; 96 | } 97 | 98 | freqLabel.text = [NSString stringWithFormat:@"%3.1f Hz", value]; 99 | 100 | } 101 | 102 | - (void) receivedAudioSamples:(SInt16 *)samples length:(int)len { 103 | [autoCorrelator addSamples:samples inNumberFrames:len]; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /PitchDetectorExample/PitchDetector.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) Kevin P Murphy June 2012 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | */ 10 | #import 11 | 12 | @protocol PitchDetectorDelegate 13 | - (void) updatedPitch: (float) frequency; 14 | @end 15 | 16 | @class AudioController; 17 | 18 | @interface PitchDetector : NSObject 19 | { 20 | float *hann, *result; 21 | SInt16 *sampleBuffer; 22 | int samplesInSampleBuffer; 23 | int bufferLength; 24 | int windowLength; 25 | } 26 | 27 | @property (nonatomic) BOOL running; 28 | @property (nonatomic, assign) id delegate; 29 | @property int hiBoundFrequency, lowBoundFrequency; 30 | @property float sampleRate; 31 | 32 | //Optional Init Method (calls the second init method but sets the frequency bounds to default values) 33 | -(id) initWithSampleRate: (float) rate andDelegate: (id) initDelegate; 34 | -(id) initWithSampleRate: (float) rate lowBoundFreq: (int) low hiBoundFreq: (int) hi andDelegate: (id) initDelegate; 35 | - (void) addSamples: (SInt16*) samples inNumberFrames: (int) frames; 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /PitchDetectorExample/PitchDetector.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) Kevin P Murphy June 2012 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | */ 10 | 11 | 12 | #import "PitchDetector.h" 13 | #import 14 | 15 | 16 | @implementation PitchDetector 17 | @synthesize lowBoundFrequency, hiBoundFrequency, sampleRate, delegate, running; 18 | 19 | #pragma mark Initialize Methods 20 | 21 | 22 | -(id) initWithSampleRate: (float) rate andDelegate: (id) initDelegate { 23 | return [self initWithSampleRate:rate lowBoundFreq:40 hiBoundFreq:4500 andDelegate:initDelegate]; 24 | } 25 | 26 | -(id) initWithSampleRate: (float) rate lowBoundFreq: (int) low hiBoundFreq: (int) hi andDelegate: (id) initDelegate { 27 | self.lowBoundFrequency = low; 28 | self.hiBoundFrequency = hi; 29 | self.sampleRate = rate; 30 | self.delegate = initDelegate; 31 | 32 | bufferLength = self.sampleRate/self.lowBoundFrequency; 33 | 34 | 35 | hann = (float*) malloc(sizeof(float)*bufferLength); 36 | vDSP_hann_window(hann, bufferLength, vDSP_HANN_NORM); 37 | 38 | sampleBuffer = (SInt16*) malloc(512); 39 | samplesInSampleBuffer = 0; 40 | 41 | result = (float*) malloc(sizeof(float)*bufferLength); 42 | 43 | return self; 44 | } 45 | 46 | #pragma mark Insert Samples 47 | 48 | - (void) addSamples:(SInt16 *)samples inNumberFrames:(int)frames { 49 | int newLength = frames; 50 | if(samplesInSampleBuffer>0) { 51 | newLength += samplesInSampleBuffer; 52 | } 53 | 54 | SInt16 *newBuffer = (SInt16*) malloc(sizeof(SInt16)*newLength); 55 | memcpy(newBuffer, sampleBuffer, samplesInSampleBuffer*sizeof(SInt16)); 56 | memcpy(&newBuffer[samplesInSampleBuffer], samples, frames*sizeof(SInt16)); 57 | 58 | free(sampleBuffer); 59 | sampleBuffer = newBuffer; 60 | samplesInSampleBuffer = newLength; 61 | 62 | if(samplesInSampleBuffer>(self.sampleRate/self.lowBoundFrequency)) { 63 | if(!self.running) { 64 | [self performSelectorInBackground:@selector(performWithNumFrames:) withObject:[NSNumber numberWithInt:newLength]]; 65 | self.running = YES; 66 | } 67 | samplesInSampleBuffer = 0; 68 | } else { 69 | //printf("NOT ENOUGH SAMPLES: %d\n", newLength); 70 | } 71 | } 72 | 73 | 74 | #pragma mark Perform Auto Correlation 75 | 76 | -(void) performWithNumFrames: (NSNumber*) numFrames; 77 | { 78 | int n = numFrames.intValue; 79 | float freq = 0; 80 | 81 | SInt16 *samples = sampleBuffer; 82 | 83 | int returnIndex = 0; 84 | float sum; 85 | bool goingUp = false; 86 | float normalize = 0; 87 | 88 | for(int i = 0; iresult[i-1] && goingUp == false && i >1) { 103 | 104 | //local min at i-1 105 | 106 | goingUp = true; 107 | 108 | } else if(goingUp == true && result[i]result[0]*0.95) { 113 | returnIndex = i-1; 114 | break; 115 | //############### NOTE ################################## 116 | // My implemenation breaks out of this loop when it finds the first peak. 117 | // This is (probably) the greatest source of error, so if you would like to 118 | // improve this algorithm, start here. the next else if() will trigger on 119 | // future local maxima (if you first take out the break; above this paragraph) 120 | //####################################################### 121 | } else if(result[i-1]>result[0]*0.85) { 122 | } 123 | goingUp = false; 124 | } 125 | } 126 | } 127 | 128 | freq =self.sampleRate/interp(result[returnIndex-1], result[returnIndex], result[returnIndex+1], returnIndex); 129 | if(freq >= 27.5 && freq <= 4500.0) { 130 | dispatch_async(dispatch_get_main_queue(), ^{ 131 | [delegate updatedPitch:freq]; 132 | }); 133 | } 134 | self.running = NO; 135 | } 136 | 137 | 138 | float interp(float y1, float y2, float y3, int k); 139 | float interp(float y1, float y2, float y3, int k) { 140 | 141 | float d, kp; 142 | d = (y3 - y1) / (2 * (2 * y2 - y1 - y3)); 143 | //printf("%f = %d + %f\n", k+d, k, d); 144 | kp = k + d; 145 | return kp; 146 | } 147 | @end 148 | 149 | -------------------------------------------------------------------------------- /PitchDetectorExample/PitchDetectorExample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.kevmdev.${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 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /PitchDetectorExample/PitchDetectorExample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PitchDetectorExample' target in the 'PitchDetectorExample' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /PitchDetectorExample/TPCircularBuffer.c: -------------------------------------------------------------------------------- 1 | // 2 | // TPCircularBuffer.c 3 | // Circular/Ring buffer implementation 4 | // 5 | // Created by Michael Tyson on 10/12/2011. 6 | // Copyright 2011 A Tasty Pixel. All rights reserved. 7 | // 8 | // MIT license: 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 11 | // associated documentation files (the "Software"), to deal in the Software without restriction, 12 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 14 | // subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all copies or substantial 17 | // portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 20 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | #include "TPCircularBuffer.h" 26 | #include 27 | #include 28 | 29 | #define checkResult(result,operation) (_checkResult((result),(operation),strrchr(__FILE__, '/'),__LINE__)) 30 | static inline bool _checkResult(kern_return_t result, const char *operation, const char* file, int line) { 31 | if ( result != ERR_SUCCESS ) { 32 | printf("%s:%d: %s: %s\n", file, line, operation, mach_error_string(result)); 33 | return false; 34 | } 35 | return true; 36 | } 37 | 38 | bool TPCircularBufferInit(TPCircularBuffer *buffer, int length) { 39 | 40 | buffer->length = round_page(length); // We need whole page sizes 41 | buffer->count = 0; 42 | // Temporarily allocate twice the length, so we have the contiguous address space to 43 | // support a second instance of the buffer directly after 44 | vm_address_t bufferAddress; 45 | if ( !checkResult(vm_allocate(mach_task_self(), &bufferAddress, buffer->length * 2, TRUE /* (don't use the current bufferAddress value) */), 46 | "Buffer allocation") ) return false; 47 | 48 | // Now replace the second half of the allocation with a virtual copy of the first half. Deallocate the second half... 49 | if ( !checkResult(vm_deallocate(mach_task_self(), bufferAddress + buffer->length, buffer->length), 50 | "Buffer deallocation") ) return false; 51 | 52 | // Then create a memory entry that refers to the buffer 53 | vm_size_t entry_length = buffer->length; 54 | mach_port_t memoryEntry; 55 | if ( !checkResult(mach_make_memory_entry(mach_task_self(), &entry_length, bufferAddress, VM_PROT_READ|VM_PROT_WRITE, &memoryEntry, 0), 56 | "Create memory entry") ) { 57 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 58 | return false; 59 | } 60 | 61 | // And map the memory entry to the address space immediately after the buffer 62 | vm_address_t virtualAddress = bufferAddress + buffer->length; 63 | if ( !checkResult(vm_map(mach_task_self(), &virtualAddress, buffer->length, 0, FALSE, memoryEntry, 0, FALSE, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE, VM_INHERIT_DEFAULT), 64 | "Map buffer memory") ) { 65 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 66 | return false; 67 | } 68 | 69 | if ( virtualAddress != bufferAddress+buffer->length ) { 70 | printf("Couldn't map buffer memory to end of buffer\n"); 71 | vm_deallocate(mach_task_self(), virtualAddress, buffer->length); 72 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 73 | return false; 74 | } 75 | 76 | buffer->buffer = (void*)bufferAddress; 77 | buffer->fillCount = 0; 78 | buffer->head = buffer->tail = 0; 79 | 80 | return true; 81 | } 82 | 83 | void TPCircularBufferCleanup(TPCircularBuffer *buffer) { 84 | vm_deallocate(mach_task_self(), (vm_address_t)buffer->buffer, buffer->length * 2); 85 | memset(buffer, 0, sizeof(TPCircularBuffer)); 86 | } 87 | 88 | void TPCircularBufferClear(TPCircularBuffer *buffer) { 89 | buffer->head = buffer->tail = 0; 90 | buffer->fillCount = 0; 91 | } 92 | -------------------------------------------------------------------------------- /PitchDetectorExample/TPCircularBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // TPCircularBuffer.h 3 | // Circular/Ring buffer implementation 4 | // 5 | // Created by Michael Tyson on 10/12/2011. 6 | // Copyright 2011 A Tasty Pixel. All rights reserved. 7 | // 8 | // 9 | // This implementation makes use of a virtual memory mapping technique that inserts a virtual copy 10 | // of the buffer memory directly after the buffer's end, negating the need for any buffer wrap-around 11 | // logic. Clients can simply use the returned memory address as if it were contiguous space. 12 | // 13 | // The implementation is thread-safe in the case of a single producer and single consumer. 14 | // 15 | // Virtual memory technique originally proposed by Philip Howard (http://vrb.slashusr.org/), and 16 | // adapted to Darwin by Kurt Revis (http://www.snoize.com, 17 | // http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz) 18 | // 19 | // MIT license: 20 | // 21 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 22 | // associated documentation files (the "Software"), to deal in the Software without restriction, 23 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 24 | // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 25 | // subject to the following conditions: 26 | // 27 | // The above copyright notice and this permission notice shall be included in all copies or substantial 28 | // portions of the Software. 29 | // 30 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 31 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 32 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 33 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 34 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35 | 36 | #include 37 | #include 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif// 42 | 43 | typedef struct { 44 | void *buffer; 45 | int32_t length; 46 | int32_t tail; 47 | int32_t head; 48 | volatile int32_t fillCount; 49 | int count; 50 | } TPCircularBuffer; 51 | 52 | bool TPCircularBufferInit(TPCircularBuffer *buffer, int32_t length); 53 | void TPCircularBufferCleanup(TPCircularBuffer *buffer); 54 | void TPCircularBufferClear(TPCircularBuffer *buffer); 55 | 56 | // Reading (consuming) 57 | 58 | static __inline__ __attribute__((always_inline)) void* TPCircularBufferTail(TPCircularBuffer *buffer, int32_t* availableBytes) { 59 | *availableBytes = buffer->fillCount; 60 | return (void*)((char*)buffer->buffer + buffer->tail); 61 | } 62 | 63 | static __inline__ __attribute__((always_inline)) void TPCircularBufferConsume(TPCircularBuffer *buffer, int32_t amount) { 64 | buffer->tail = (buffer->tail + amount) % buffer->length; 65 | OSAtomicAdd32Barrier(-amount, &buffer->fillCount); 66 | buffer->count -= amount; 67 | } 68 | 69 | static __inline__ __attribute__((always_inline)) void* TPCircularBufferHead(TPCircularBuffer *buffer, int32_t * availableBytes) { 70 | *availableBytes = (buffer->length - buffer->fillCount); 71 | return (void*)((char*)buffer->buffer + buffer->head); 72 | } 73 | 74 | // Writing (producing) 75 | 76 | static __inline__ __attribute__((always_inline)) void TPCircularBufferProduce(TPCircularBuffer *buffer, int amount) { 77 | buffer->head = (buffer->head + amount) % buffer->length; 78 | OSAtomicAdd32Barrier(amount, &buffer->fillCount); 79 | buffer->count += amount; 80 | } 81 | 82 | static __inline__ __attribute__((always_inline)) int TPCircularBufferProduceBytes(TPCircularBuffer *buffer, const void* src, int32_t len) { 83 | int32_t space; 84 | void *ptr = TPCircularBufferHead(buffer, &space); 85 | int copied = len > space ? space : len; 86 | memcpy(ptr, src, copied); 87 | TPCircularBufferProduce(buffer, copied); 88 | return copied; 89 | } 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | -------------------------------------------------------------------------------- /PitchDetectorExample/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /PitchDetectorExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PitchDetectorExample 4 | // 5 | // Created by Kevin Murphy on 7/4/12. 6 | // Copyright (c) 2012 New York University. 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 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | This was written a some time ago and is not a great example. It might be helpful to get you started on your own project, but you've been warned that this is by no means an example of good coding practices. 2 | --------------------------------------------------------------------------------