├── .DS_Store ├── .gitignore ├── AudioUnitSample ├── .DS_Store ├── AudioUnitSample.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── MixPlaying │ ├── .DS_Store │ ├── MixPlaying.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── MixPlaying │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── SKAudioBuffer.h │ │ ├── SKAudioBuffer.m │ │ ├── SKAudioConverter.h │ │ ├── SKAudioConverter.m │ │ ├── SKAudioParser.h │ │ ├── SKAudioParser.m │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ └── main.m ├── RemoteInput │ ├── .DS_Store │ ├── RemoteInput.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── RemoteInput │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── SKAudioBuffer.h │ │ ├── SKAudioBuffer.m │ │ ├── SKAudioConverter.h │ │ ├── SKAudioConverter.m │ │ ├── SKAudioParser.h │ │ ├── SKAudioParser.m │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ └── main.m └── SimplePlaying │ ├── .DS_Store │ ├── SimplePlaying.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── SimplePlaying │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── SKAudioBuffer.h │ ├── SKAudioBuffer.m │ ├── SKAudioConverter.h │ ├── SKAudioConverter.m │ ├── SKAudioParser.h │ ├── SKAudioParser.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StevenKuo/AudioUnitSample/b50c8111600d283cbde02ce48f1ae36b3aa49f61/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /AudioUnitSample/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StevenKuo/AudioUnitSample/b50c8111600d283cbde02ce48f1ae36b3aa49f61/AudioUnitSample/.DS_Store -------------------------------------------------------------------------------- /AudioUnitSample/AudioUnitSample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /AudioUnitSample/AudioUnitSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StevenKuo/AudioUnitSample/b50c8111600d283cbde02ce48f1ae36b3aa49f61/AudioUnitSample/MixPlaying/.DS_Store -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9CCFA5A21BFDDFF400981DA9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCFA5A11BFDDFF400981DA9 /* main.m */; }; 11 | 9CCFA5A51BFDDFF400981DA9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCFA5A41BFDDFF400981DA9 /* AppDelegate.m */; }; 12 | 9CCFA5A81BFDDFF400981DA9 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCFA5A71BFDDFF400981DA9 /* ViewController.m */; }; 13 | 9CCFA5AB1BFDDFF400981DA9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9CCFA5A91BFDDFF400981DA9 /* Main.storyboard */; }; 14 | 9CCFA5AD1BFDDFF400981DA9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9CCFA5AC1BFDDFF400981DA9 /* Assets.xcassets */; }; 15 | 9CCFA5B01BFDDFF400981DA9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9CCFA5AE1BFDDFF400981DA9 /* LaunchScreen.storyboard */; }; 16 | 9CCFA5BD1BFDE01700981DA9 /* SKAudioBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCFA5B81BFDE01700981DA9 /* SKAudioBuffer.m */; }; 17 | 9CCFA5BE1BFDE01700981DA9 /* SKAudioConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCFA5BA1BFDE01700981DA9 /* SKAudioConverter.m */; }; 18 | 9CCFA5BF1BFDE01700981DA9 /* SKAudioParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCFA5BC1BFDE01700981DA9 /* SKAudioParser.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 9CCFA59D1BFDDFF400981DA9 /* MixPlaying.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MixPlaying.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 9CCFA5A11BFDDFF400981DA9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 24 | 9CCFA5A31BFDDFF400981DA9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 25 | 9CCFA5A41BFDDFF400981DA9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 26 | 9CCFA5A61BFDDFF400981DA9 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 27 | 9CCFA5A71BFDDFF400981DA9 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 28 | 9CCFA5AA1BFDDFF400981DA9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 9CCFA5AC1BFDDFF400981DA9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 9CCFA5AF1BFDDFF400981DA9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 9CCFA5B11BFDDFF400981DA9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 9CCFA5B71BFDE01700981DA9 /* SKAudioBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SKAudioBuffer.h; sourceTree = ""; }; 33 | 9CCFA5B81BFDE01700981DA9 /* SKAudioBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKAudioBuffer.m; sourceTree = ""; }; 34 | 9CCFA5B91BFDE01700981DA9 /* SKAudioConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SKAudioConverter.h; sourceTree = ""; }; 35 | 9CCFA5BA1BFDE01700981DA9 /* SKAudioConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKAudioConverter.m; sourceTree = ""; }; 36 | 9CCFA5BB1BFDE01700981DA9 /* SKAudioParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SKAudioParser.h; sourceTree = ""; }; 37 | 9CCFA5BC1BFDE01700981DA9 /* SKAudioParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKAudioParser.m; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | 9CCFA59A1BFDDFF400981DA9 /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 9CCFA5941BFDDFF400981DA9 = { 52 | isa = PBXGroup; 53 | children = ( 54 | 9CCFA59F1BFDDFF400981DA9 /* MixPlaying */, 55 | 9CCFA59E1BFDDFF400981DA9 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | 9CCFA59E1BFDDFF400981DA9 /* Products */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | 9CCFA59D1BFDDFF400981DA9 /* MixPlaying.app */, 63 | ); 64 | name = Products; 65 | sourceTree = ""; 66 | }; 67 | 9CCFA59F1BFDDFF400981DA9 /* MixPlaying */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 9CCFA5B71BFDE01700981DA9 /* SKAudioBuffer.h */, 71 | 9CCFA5B81BFDE01700981DA9 /* SKAudioBuffer.m */, 72 | 9CCFA5B91BFDE01700981DA9 /* SKAudioConverter.h */, 73 | 9CCFA5BA1BFDE01700981DA9 /* SKAudioConverter.m */, 74 | 9CCFA5BB1BFDE01700981DA9 /* SKAudioParser.h */, 75 | 9CCFA5BC1BFDE01700981DA9 /* SKAudioParser.m */, 76 | 9CCFA5A31BFDDFF400981DA9 /* AppDelegate.h */, 77 | 9CCFA5A41BFDDFF400981DA9 /* AppDelegate.m */, 78 | 9CCFA5A61BFDDFF400981DA9 /* ViewController.h */, 79 | 9CCFA5A71BFDDFF400981DA9 /* ViewController.m */, 80 | 9CCFA5A91BFDDFF400981DA9 /* Main.storyboard */, 81 | 9CCFA5AC1BFDDFF400981DA9 /* Assets.xcassets */, 82 | 9CCFA5AE1BFDDFF400981DA9 /* LaunchScreen.storyboard */, 83 | 9CCFA5B11BFDDFF400981DA9 /* Info.plist */, 84 | 9CCFA5A01BFDDFF400981DA9 /* Supporting Files */, 85 | ); 86 | path = MixPlaying; 87 | sourceTree = ""; 88 | }; 89 | 9CCFA5A01BFDDFF400981DA9 /* Supporting Files */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 9CCFA5A11BFDDFF400981DA9 /* main.m */, 93 | ); 94 | name = "Supporting Files"; 95 | sourceTree = ""; 96 | }; 97 | /* End PBXGroup section */ 98 | 99 | /* Begin PBXNativeTarget section */ 100 | 9CCFA59C1BFDDFF400981DA9 /* MixPlaying */ = { 101 | isa = PBXNativeTarget; 102 | buildConfigurationList = 9CCFA5B41BFDDFF400981DA9 /* Build configuration list for PBXNativeTarget "MixPlaying" */; 103 | buildPhases = ( 104 | 9CCFA5991BFDDFF400981DA9 /* Sources */, 105 | 9CCFA59A1BFDDFF400981DA9 /* Frameworks */, 106 | 9CCFA59B1BFDDFF400981DA9 /* Resources */, 107 | ); 108 | buildRules = ( 109 | ); 110 | dependencies = ( 111 | ); 112 | name = MixPlaying; 113 | productName = MixPlaying; 114 | productReference = 9CCFA59D1BFDDFF400981DA9 /* MixPlaying.app */; 115 | productType = "com.apple.product-type.application"; 116 | }; 117 | /* End PBXNativeTarget section */ 118 | 119 | /* Begin PBXProject section */ 120 | 9CCFA5951BFDDFF400981DA9 /* Project object */ = { 121 | isa = PBXProject; 122 | attributes = { 123 | LastUpgradeCheck = 0710; 124 | ORGANIZATIONNAME = StevenKuo; 125 | TargetAttributes = { 126 | 9CCFA59C1BFDDFF400981DA9 = { 127 | CreatedOnToolsVersion = 7.1.1; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = 9CCFA5981BFDDFF400981DA9 /* Build configuration list for PBXProject "MixPlaying" */; 132 | compatibilityVersion = "Xcode 3.2"; 133 | developmentRegion = English; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = 9CCFA5941BFDDFF400981DA9; 140 | productRefGroup = 9CCFA59E1BFDDFF400981DA9 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | 9CCFA59C1BFDDFF400981DA9 /* MixPlaying */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXResourcesBuildPhase section */ 150 | 9CCFA59B1BFDDFF400981DA9 /* Resources */ = { 151 | isa = PBXResourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | 9CCFA5B01BFDDFF400981DA9 /* LaunchScreen.storyboard in Resources */, 155 | 9CCFA5AD1BFDDFF400981DA9 /* Assets.xcassets in Resources */, 156 | 9CCFA5AB1BFDDFF400981DA9 /* Main.storyboard in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXSourcesBuildPhase section */ 163 | 9CCFA5991BFDDFF400981DA9 /* Sources */ = { 164 | isa = PBXSourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | 9CCFA5BE1BFDE01700981DA9 /* SKAudioConverter.m in Sources */, 168 | 9CCFA5BD1BFDE01700981DA9 /* SKAudioBuffer.m in Sources */, 169 | 9CCFA5A81BFDDFF400981DA9 /* ViewController.m in Sources */, 170 | 9CCFA5BF1BFDE01700981DA9 /* SKAudioParser.m in Sources */, 171 | 9CCFA5A51BFDDFF400981DA9 /* AppDelegate.m in Sources */, 172 | 9CCFA5A21BFDDFF400981DA9 /* main.m in Sources */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXSourcesBuildPhase section */ 177 | 178 | /* Begin PBXVariantGroup section */ 179 | 9CCFA5A91BFDDFF400981DA9 /* Main.storyboard */ = { 180 | isa = PBXVariantGroup; 181 | children = ( 182 | 9CCFA5AA1BFDDFF400981DA9 /* Base */, 183 | ); 184 | name = Main.storyboard; 185 | sourceTree = ""; 186 | }; 187 | 9CCFA5AE1BFDDFF400981DA9 /* LaunchScreen.storyboard */ = { 188 | isa = PBXVariantGroup; 189 | children = ( 190 | 9CCFA5AF1BFDDFF400981DA9 /* Base */, 191 | ); 192 | name = LaunchScreen.storyboard; 193 | sourceTree = ""; 194 | }; 195 | /* End PBXVariantGroup section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | 9CCFA5B21BFDDFF400981DA9 /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 203 | CLANG_CXX_LIBRARY = "libc++"; 204 | CLANG_ENABLE_MODULES = YES; 205 | CLANG_ENABLE_OBJC_ARC = YES; 206 | CLANG_WARN_BOOL_CONVERSION = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 216 | COPY_PHASE_STRIP = NO; 217 | DEBUG_INFORMATION_FORMAT = dwarf; 218 | ENABLE_STRICT_OBJC_MSGSEND = YES; 219 | ENABLE_TESTABILITY = YES; 220 | GCC_C_LANGUAGE_STANDARD = gnu99; 221 | GCC_DYNAMIC_NO_PIC = NO; 222 | GCC_NO_COMMON_BLOCKS = YES; 223 | GCC_OPTIMIZATION_LEVEL = 0; 224 | GCC_PREPROCESSOR_DEFINITIONS = ( 225 | "DEBUG=1", 226 | "$(inherited)", 227 | ); 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 235 | MTL_ENABLE_DEBUG_INFO = YES; 236 | ONLY_ACTIVE_ARCH = YES; 237 | SDKROOT = iphoneos; 238 | TARGETED_DEVICE_FAMILY = "1,2"; 239 | }; 240 | name = Debug; 241 | }; 242 | 9CCFA5B31BFDDFF400981DA9 /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 247 | CLANG_CXX_LIBRARY = "libc++"; 248 | CLANG_ENABLE_MODULES = YES; 249 | CLANG_ENABLE_OBJC_ARC = YES; 250 | CLANG_WARN_BOOL_CONVERSION = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INT_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_UNREACHABLE_CODE = YES; 258 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 259 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 260 | COPY_PHASE_STRIP = NO; 261 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 262 | ENABLE_NS_ASSERTIONS = NO; 263 | ENABLE_STRICT_OBJC_MSGSEND = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_NO_COMMON_BLOCKS = YES; 266 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 267 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 268 | GCC_WARN_UNDECLARED_SELECTOR = YES; 269 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 270 | GCC_WARN_UNUSED_FUNCTION = YES; 271 | GCC_WARN_UNUSED_VARIABLE = YES; 272 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 273 | MTL_ENABLE_DEBUG_INFO = NO; 274 | SDKROOT = iphoneos; 275 | TARGETED_DEVICE_FAMILY = "1,2"; 276 | VALIDATE_PRODUCT = YES; 277 | }; 278 | name = Release; 279 | }; 280 | 9CCFA5B51BFDDFF400981DA9 /* Debug */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 284 | INFOPLIST_FILE = MixPlaying/Info.plist; 285 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 286 | PRODUCT_BUNDLE_IDENTIFIER = SK.MixPlaying; 287 | PRODUCT_NAME = "$(TARGET_NAME)"; 288 | }; 289 | name = Debug; 290 | }; 291 | 9CCFA5B61BFDDFF400981DA9 /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 295 | INFOPLIST_FILE = MixPlaying/Info.plist; 296 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 297 | PRODUCT_BUNDLE_IDENTIFIER = SK.MixPlaying; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | }; 300 | name = Release; 301 | }; 302 | /* End XCBuildConfiguration section */ 303 | 304 | /* Begin XCConfigurationList section */ 305 | 9CCFA5981BFDDFF400981DA9 /* Build configuration list for PBXProject "MixPlaying" */ = { 306 | isa = XCConfigurationList; 307 | buildConfigurations = ( 308 | 9CCFA5B21BFDDFF400981DA9 /* Debug */, 309 | 9CCFA5B31BFDDFF400981DA9 /* Release */, 310 | ); 311 | defaultConfigurationIsVisible = 0; 312 | defaultConfigurationName = Release; 313 | }; 314 | 9CCFA5B41BFDDFF400981DA9 /* Build configuration list for PBXNativeTarget "MixPlaying" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | 9CCFA5B51BFDDFF400981DA9 /* Debug */, 318 | 9CCFA5B61BFDDFF400981DA9 /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | }; 322 | /* End XCConfigurationList section */ 323 | }; 324 | rootObject = 9CCFA5951BFDDFF400981DA9 /* Project object */; 325 | } 326 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MixPlaying 4 | // 5 | // Created by StevenKuo on 2015/11/19. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MixPlaying 4 | // 5 | // Created by StevenKuo on 2015/11/19. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/Assets.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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 49 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/SKAudioBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioBuffer.h 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef struct { 13 | AudioStreamPacketDescription packetDescription; 14 | void *data; 15 | } AudioPacketInfo; 16 | 17 | @class SKAudioBuffer; 18 | 19 | @protocol SKAudioBufferDelegate 20 | 21 | - (AudioStreamBasicDescription)usedAudioStreamBasicDescription; 22 | - (void)audioBufferDidBeginReadPacket:(SKAudioBuffer *)inBuffer; 23 | @end 24 | 25 | @interface SKAudioBuffer : NSObject 26 | { 27 | __weak id delegate; 28 | 29 | AudioPacketInfo *packets; 30 | size_t packetWriteIndex; 31 | size_t packetReadIndex; 32 | size_t packetCount; 33 | 34 | NSMutableData *audioData; 35 | NSMutableData *packetDescData; 36 | NSUInteger packetReadHead; 37 | NSUInteger readPacketIndex; 38 | } 39 | 40 | 41 | - (void)storePacketData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount; 42 | - (void)movePacketReadIndex; 43 | 44 | @property (readonly, nonatomic) size_t availablePacketCount; 45 | @property (weak, nonatomic) id delegate; 46 | @property (readonly, nonatomic) AudioPacketInfo currentPacketInfo; 47 | @end 48 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/SKAudioBuffer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioBuffer.m 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import "SKAudioBuffer.h" 10 | 11 | @implementation SKAudioBuffer 12 | 13 | - (id)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | 18 | packetCount = 2048; 19 | packets = (AudioPacketInfo *)calloc(packetCount, sizeof(AudioPacketInfo)); 20 | 21 | audioData = [[NSMutableData alloc] init]; 22 | packetDescData = [[NSMutableData alloc] init]; 23 | } 24 | return self; 25 | } 26 | 27 | 28 | - (void)storePacketData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount 29 | { 30 | // for (NSUInteger packetIndex = 0; packetIndex < inPacketsCount ; packetIndex ++) { 31 | // inPacketDescriptions[packetIndex].mStartOffset += audioData.length; 32 | // } 33 | // 34 | // @synchronized (self) { 35 | // [audioData appendBytes:inBytes length:inLength]; 36 | // [packetDescData appendBytes:inPacketDescriptions length:sizeof(AudioStreamPacketDescription) * inPacketsCount]; 37 | // availablePacketCount += inPacketsCount; 38 | // } 39 | 40 | @synchronized (self) { 41 | 42 | for (size_t index = 0; index < inPacketsCount; index ++) { 43 | 44 | if (packetWriteIndex >= packetCount) { 45 | size_t oldSize = packetCount * sizeof(AudioPacketInfo); 46 | packetCount = packetCount * 2; 47 | packets = (AudioPacketInfo *)realloc(packets, packetCount * sizeof(AudioPacketInfo)); 48 | bzero((void *)packets + oldSize, oldSize); 49 | } 50 | AudioStreamPacketDescription emptyDescription; 51 | 52 | if (!inPacketDescriptions) { 53 | emptyDescription.mStartOffset = index; 54 | emptyDescription.mDataByteSize = 1; 55 | emptyDescription.mVariableFramesInPacket = 0; 56 | } 57 | 58 | AudioStreamPacketDescription *currentDescription = inPacketDescriptions ? &(inPacketDescriptions[index]) : &emptyDescription; 59 | 60 | AudioPacketInfo *nextInfo = &packets[packetWriteIndex]; 61 | if (nextInfo->data) { 62 | free(nextInfo->data); 63 | nextInfo->data = NULL; 64 | } 65 | nextInfo->data = malloc(currentDescription->mDataByteSize); 66 | NSAssert(nextInfo->data, @"Must allocate memory for current packet"); 67 | memcpy(nextInfo->data, inBytes + currentDescription->mStartOffset, currentDescription->mDataByteSize); 68 | memcpy(&nextInfo->packetDescription, currentDescription, sizeof(AudioStreamPacketDescription)); 69 | 70 | packetWriteIndex++; 71 | 72 | _availablePacketCount++; 73 | } 74 | } 75 | } 76 | 77 | - (void)setPacketReadIndex:(size_t)inNewIndex 78 | { 79 | size_t max = _availablePacketCount; 80 | 81 | if (inNewIndex > max) { 82 | packetReadIndex = max; 83 | return; 84 | } 85 | 86 | if (inNewIndex < packetWriteIndex) { 87 | packetReadIndex = inNewIndex; 88 | } 89 | else { 90 | packetReadIndex = packetWriteIndex; 91 | } 92 | } 93 | 94 | - (void)movePacketReadIndex 95 | { 96 | [self setPacketReadIndex:packetReadIndex + 1]; 97 | } 98 | 99 | - (AudioPacketInfo)currentPacketInfo 100 | { 101 | // @synchronized (self) { 102 | // if (readPacketIndex >= availablePacketCount) { 103 | // inCallback(nil, 0, nil, YES); 104 | // return; 105 | // } 106 | // if (readPacketIndex == 0) { 107 | // [delegate audioBufferDidBeginReadPacket:self]; 108 | // } 109 | // 110 | // AudioStreamPacketDescription* packetDescriptions = (AudioStreamPacketDescription* )packetDescData.bytes; 111 | // 112 | // AudioPacketInfo *packet = (AudioPacketInfo *)calloc(1, sizeof(AudioPacketInfo)); 113 | // packet->data = malloc(packetDescriptions[readPacketIndex].mDataByteSize); 114 | // memcpy(packet->data, audioData.bytes + packetDescriptions[readPacketIndex].mStartOffset, packetDescriptions[readPacketIndex].mDataByteSize); 115 | // memcpy(&packet->packetDescription, &packetDescriptions[readPacketIndex], sizeof(AudioStreamPacketDescription)); 116 | // 117 | // readPacketIndex ++; 118 | // 119 | // return *packet; 120 | // } 121 | return packets[packetReadIndex]; 122 | } 123 | 124 | @synthesize delegate; 125 | @synthesize currentPacketInfo; 126 | @end 127 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/SKAudioConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioConverter.h 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SKAudioBuffer.h" 12 | 13 | @interface SKAudioConverter : NSObject 14 | { 15 | AudioStreamBasicDescription audioStreamDescription; 16 | AudioStreamBasicDescription destFormat; 17 | AudioConverterRef converter; 18 | AudioBufferList *renderBufferList; 19 | UInt32 renderBufferSize; 20 | } 21 | 22 | AudioStreamBasicDescription LinearPCMStreamDescription(); 23 | 24 | - (instancetype)initWithSourceFormat:(AudioStreamBasicDescription *)sourceFormat; 25 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber buffer:(SKAudioBuffer *)inBuffer; 26 | 27 | - (void)_fillBufferlist:(AudioBufferList *)ioData withBuffer:(SKAudioBuffer *)buffer packetDescription:(AudioStreamPacketDescription** )outDataPacketDescription; 28 | @property (readonly, nonatomic) double packetsPerSecond; 29 | @end 30 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/SKAudioConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioConverter.m 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "SKAudioConverter.h" 10 | 11 | static OSStatus AudioConverterFiller(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData); 12 | 13 | OSStatus AudioConverterFiller (AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) 14 | { 15 | NSArray *args = (__bridge NSArray *)inUserData; 16 | SKAudioConverter *self = args[0]; 17 | SKAudioBuffer *buffer = args[1]; 18 | // *ioNumberDataPackets = 1; 19 | [self _fillBufferlist:ioData withBuffer:buffer packetDescription:outDataPacketDescription]; 20 | return noErr; 21 | } 22 | 23 | AudioStreamBasicDescription LinearPCMStreamDescription() 24 | { 25 | AudioStreamBasicDescription destFormat; 26 | bzero(&destFormat, sizeof(AudioStreamBasicDescription)); 27 | destFormat.mSampleRate = 44100.0; 28 | destFormat.mFormatID = kAudioFormatLinearPCM; 29 | destFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; 30 | 31 | destFormat.mFramesPerPacket = 1; 32 | destFormat.mBytesPerPacket = 4; 33 | destFormat.mBytesPerFrame = 4; 34 | destFormat.mChannelsPerFrame = 2; 35 | destFormat.mBitsPerChannel = 16; 36 | destFormat.mReserved = 0; 37 | return destFormat; 38 | } 39 | 40 | @implementation SKAudioConverter 41 | 42 | - (instancetype)initWithSourceFormat:(AudioStreamBasicDescription *)sourceFormat 43 | { 44 | self = [super init]; 45 | if (self) { 46 | audioStreamDescription = *sourceFormat; 47 | destFormat = LinearPCMStreamDescription(); 48 | AudioConverterNew(&audioStreamDescription, &destFormat, &converter); 49 | 50 | UInt32 packetSize = 44100 * 4; 51 | renderBufferSize = packetSize; 52 | renderBufferList = (AudioBufferList *)calloc(1, sizeof(UInt32) + sizeof(AudioBuffer)); 53 | renderBufferList->mNumberBuffers = 1; 54 | renderBufferList->mBuffers[0].mNumberChannels = 2; 55 | renderBufferList->mBuffers[0].mDataByteSize = packetSize; 56 | renderBufferList->mBuffers[0].mData = calloc(1, packetSize); 57 | } 58 | return self; 59 | } 60 | 61 | - (void)_fillBufferlist:(AudioBufferList *)ioData withBuffer:(SKAudioBuffer *)buffer packetDescription:(AudioStreamPacketDescription** )outDataPacketDescription 62 | { 63 | static AudioStreamPacketDescription aspdesc; 64 | 65 | AudioPacketInfo currentPacketInfo = buffer.currentPacketInfo; 66 | 67 | void *data = currentPacketInfo.data; 68 | UInt32 length = (UInt32)currentPacketInfo.packetDescription.mDataByteSize; 69 | ioData->mBuffers[0].mData = data; 70 | ioData->mBuffers[0].mDataByteSize = length; 71 | ioData->mNumberBuffers = 1; 72 | 73 | *outDataPacketDescription = &aspdesc; 74 | aspdesc.mDataByteSize = length; 75 | aspdesc.mStartOffset = 0; 76 | aspdesc.mVariableFramesInPacket = 1; 77 | 78 | [buffer movePacketReadIndex]; 79 | } 80 | 81 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber buffer:(SKAudioBuffer *)inBuffer 82 | { 83 | UInt32 packetSize = inNumberOfFrames; 84 | NSArray *args = @[self, inBuffer]; 85 | OSStatus status = noErr; 86 | 87 | status = AudioConverterFillComplexBuffer(converter, AudioConverterFiller, (__bridge void *)(args), &packetSize, renderBufferList, NULL); 88 | 89 | if (noErr == status && packetSize) { 90 | inIoData->mNumberBuffers = 1; 91 | inIoData->mBuffers[0].mNumberChannels = 2; 92 | inIoData->mBuffers[0].mDataByteSize = renderBufferList->mBuffers[0].mDataByteSize; 93 | inIoData->mBuffers[0].mData = renderBufferList->mBuffers[0].mData; 94 | status = noErr; 95 | } 96 | return status; 97 | } 98 | 99 | - (double)packetsPerSecond 100 | { 101 | if (!(audioStreamDescription.mFramesPerPacket > 0)) { 102 | return 0; 103 | } 104 | return audioStreamDescription.mSampleRate / audioStreamDescription.mFramesPerPacket; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/SKAudioParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioParser.h 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class SKAudioParser; 13 | 14 | @protocol SKAudioParserDelegate 15 | 16 | - (void)audioStreamParser:(SKAudioParser *)inParser didObtainStreamDescription:(AudioStreamBasicDescription *)inDescription; 17 | - (void)audioStreamParser:(SKAudioParser *)inParser packetData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount; 18 | 19 | @end 20 | 21 | @interface SKAudioParser : NSObject 22 | { 23 | AudioFileStreamID audioFileStreamID; 24 | __weak id delegate; 25 | } 26 | 27 | - (void)parseData:(NSData *)inData; 28 | 29 | @property (weak, nonatomic) id delegate; 30 | @end 31 | 32 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/SKAudioParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioParser.m 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import "SKAudioParser.h" 10 | 11 | @implementation SKAudioParser 12 | 13 | 14 | void audioFileStreamPropertyListenerProc(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags) 15 | { 16 | /* 17 | kAudioFileStreamProperty_ReadyToProducePackets = 'redy', 18 | kAudioFileStreamProperty_FileFormat = 'ffmt', 19 | kAudioFileStreamProperty_DataFormat = 'dfmt', 20 | kAudioFileStreamProperty_FormatList = 'flst', 21 | kAudioFileStreamProperty_MagicCookieData = 'mgic', 22 | kAudioFileStreamProperty_AudioDataByteCount = 'bcnt', 23 | kAudioFileStreamProperty_AudioDataPacketCount = 'pcnt', 24 | kAudioFileStreamProperty_MaximumPacketSize = 'psze', 25 | kAudioFileStreamProperty_DataOffset = 'doff', 26 | kAudioFileStreamProperty_ChannelLayout = 'cmap', 27 | kAudioFileStreamProperty_PacketToFrame = 'pkfr', 28 | kAudioFileStreamProperty_FrameToPacket = 'frpk', 29 | kAudioFileStreamProperty_PacketToByte = 'pkby', 30 | kAudioFileStreamProperty_ByteToPacket = 'bypk', 31 | kAudioFileStreamProperty_PacketTableInfo = 'pnfo', 32 | kAudioFileStreamProperty_PacketSizeUpperBound = 'pkub', 33 | kAudioFileStreamProperty_AverageBytesPerPacket = 'abpp', 34 | kAudioFileStreamProperty_BitRate = 'brat', 35 | kAudioFileStreamProperty_InfoDictionary = 'info' 36 | */ 37 | if (inPropertyID == 'dfmt') { 38 | AudioStreamBasicDescription description; 39 | UInt32 descriptionSize = sizeof(description); 40 | AudioFileStreamGetProperty(inAudioFileStream, inPropertyID, &descriptionSize, &description); 41 | [((__bridge SKAudioParser *)inClientData).delegate audioStreamParser:(__bridge SKAudioParser *)inClientData didObtainStreamDescription:&description]; 42 | } 43 | } 44 | 45 | 46 | void audioFileStreamPacketsProc(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions) 47 | { 48 | [((__bridge SKAudioParser *)inClientData).delegate audioStreamParser:((__bridge SKAudioParser *)inClientData) packetData:inInputData dataLength:inNumberBytes packetDescriptions:inPacketDescriptions packetsCount:inNumberPackets]; 49 | 50 | } 51 | 52 | - (id)init 53 | { 54 | self = [super init]; 55 | if (self) { 56 | 57 | AudioFileStreamOpen((__bridge void *)(self), audioFileStreamPropertyListenerProc, audioFileStreamPacketsProc, kAudioFileMP3Type, &audioFileStreamID); 58 | 59 | } 60 | return self; 61 | } 62 | 63 | - (void)parseData:(NSData *)inData 64 | { 65 | AudioFileStreamParseBytes(audioFileStreamID, (UInt32)[inData length], [inData bytes], 0); 66 | } 67 | 68 | @synthesize delegate; 69 | @end 70 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MixPlaying 4 | // 5 | // Created by StevenKuo on 2015/11/19. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // MixPlaying 4 | // 5 | // Created by StevenKuo on 2015/11/19. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import 12 | #import "SKAudioParser.h" 13 | #import "SKAudioBuffer.h" 14 | #import "SKAudioConverter.h" 15 | 16 | @interface ViewController () 17 | { 18 | AUGraph audioGraph; 19 | AUNode mixNode; 20 | AudioUnit mixAudioUnit; 21 | AUNode outputNode; 22 | AudioUnit outputAudioUnit; 23 | 24 | SKAudioParser *parser; 25 | SKAudioBuffer *buffer; 26 | SKAudioBuffer *buffer2; 27 | SKAudioParser *parser2; 28 | 29 | SKAudioConverter *converter; 30 | SKAudioConverter *converter2; 31 | 32 | NSURLSessionDataTask *task1; 33 | NSURLSessionDataTask *task2; 34 | 35 | BOOL firstComplete; 36 | IBOutlet UITextField *textFeild; 37 | IBOutlet UITextField *textFeild2; 38 | IBOutlet UILabel *tip; 39 | } 40 | 41 | @end 42 | 43 | static void MyAudioUnitPropertyListenerProc(void *inRefCon, AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope,AudioUnitElement inElement); 44 | 45 | static OSStatus RenderCallback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); 46 | static OSStatus RenderCallback2(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); 47 | 48 | @implementation ViewController 49 | 50 | - (id)initWithCoder:(NSCoder *)aDecoder 51 | { 52 | self = [super initWithCoder:aDecoder]; 53 | if (self) { 54 | parser = [[SKAudioParser alloc] init]; 55 | parser.delegate = self; 56 | 57 | parser2 = [[SKAudioParser alloc] init]; 58 | parser2.delegate = self; 59 | 60 | buffer = [[SKAudioBuffer alloc] init]; 61 | 62 | 63 | buffer2 = [[SKAudioBuffer alloc] init]; 64 | 65 | 66 | OSStatus status = noErr; 67 | status = NewAUGraph(&audioGraph); 68 | status = AUGraphOpen(audioGraph); 69 | 70 | AudioComponentDescription outputUnitDescription = [self outputUnitDescription]; 71 | status = AUGraphAddNode(audioGraph, &outputUnitDescription, &outputNode); 72 | status = AUGraphNodeInfo(audioGraph, outputNode, &outputUnitDescription, &outputAudioUnit); 73 | UInt32 maxFPS = 4096; 74 | status = AudioUnitSetProperty(outputAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0,&maxFPS, sizeof(maxFPS)); 75 | 76 | AudioComponentDescription mixUnitDescription = [self mixUnitDescription]; 77 | status = AUGraphAddNode(audioGraph, &mixUnitDescription, &mixNode); 78 | status = AUGraphNodeInfo(audioGraph, mixNode, &mixUnitDescription, &mixAudioUnit); 79 | status = AudioUnitSetProperty(mixAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0,&maxFPS, sizeof(maxFPS)); 80 | 81 | status = AUGraphConnectNodeInput(audioGraph, mixNode, 0, outputNode, 0); 82 | 83 | AudioStreamBasicDescription destFormat = LinearPCMStreamDescription(); 84 | 85 | status = AudioUnitSetProperty(mixAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &destFormat, sizeof(destFormat)); 86 | 87 | status = AudioUnitSetProperty(mixAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &destFormat, sizeof(destFormat)); 88 | 89 | status = AudioUnitSetProperty(mixAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &destFormat, sizeof(destFormat)); 90 | 91 | status = AudioUnitSetProperty(outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &destFormat, sizeof(destFormat)); 92 | 93 | // status = AudioUnitSetParameter(mixAudioUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, 0.5, 0); 94 | // status = AudioUnitSetParameter(mixAudioUnit, kMultiChannelMixerParam_Pan, kAudioUnitScope_Input, 0, 1, 1); 95 | // status = AudioUnitSetParameter(mixAudioUnit, kMultiChannelMixerParam_Pan, kAudioUnitScope_Input, 1, -1, 1); 96 | 97 | 98 | status = AudioUnitAddPropertyListener(outputAudioUnit, kAudioOutputUnitProperty_IsRunning, MyAudioUnitPropertyListenerProc, (__bridge void *)(self)); 99 | 100 | AURenderCallbackStruct callbackStruct; 101 | callbackStruct.inputProcRefCon = (__bridge void *)(self); 102 | callbackStruct.inputProc = RenderCallback; 103 | status = AUGraphSetNodeInputCallback(audioGraph, mixNode, 0, &callbackStruct); 104 | 105 | AURenderCallbackStruct callbackStruct2; 106 | callbackStruct2.inputProcRefCon = (__bridge void *)(self); 107 | callbackStruct2.inputProc = RenderCallback2; 108 | status = AUGraphSetNodeInputCallback(audioGraph, mixNode, 1, &callbackStruct2); 109 | 110 | status = AUGraphInitialize(audioGraph); 111 | AudioOutputUnitStop(outputAudioUnit); 112 | } 113 | return self; 114 | } 115 | 116 | - (AudioComponentDescription)outputUnitDescription 117 | { 118 | AudioComponentDescription outputUnitDescription; 119 | bzero(&outputUnitDescription, sizeof(AudioComponentDescription)); 120 | outputUnitDescription.componentType = kAudioUnitType_Output; 121 | outputUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO; 122 | outputUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 123 | outputUnitDescription.componentFlags = 0; 124 | outputUnitDescription.componentFlagsMask = 0; 125 | return outputUnitDescription; 126 | } 127 | 128 | - (AudioComponentDescription)mixUnitDescription 129 | { 130 | AudioComponentDescription mixerUnitDescription; 131 | bzero(&mixerUnitDescription, sizeof(AudioComponentDescription)); 132 | mixerUnitDescription.componentType = kAudioUnitType_Mixer; 133 | mixerUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer; 134 | mixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 135 | mixerUnitDescription.componentFlags = 0; 136 | mixerUnitDescription.componentFlagsMask = 0; 137 | return mixerUnitDescription; 138 | } 139 | 140 | 141 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 142 | [textField resignFirstResponder]; 143 | [textField setEnabled:NO]; 144 | return YES; 145 | } 146 | 147 | - (void)textFieldDidEndEditing:(UITextField *)textField { 148 | [textField resignFirstResponder]; 149 | [textField setEnabled:NO]; 150 | if (textFeild.text.length != 0 && textFeild2.text.length != 0) { 151 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 152 | NSURLSessionConfiguration *myConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; 153 | NSURLSession *operationSession = [NSURLSession sessionWithConfiguration:myConfiguration delegate:(id)self delegateQueue:operationQueue]; 154 | 155 | NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:textFeild.text]]; 156 | task1 = [operationSession dataTaskWithRequest:request]; 157 | [task1 resume]; 158 | 159 | NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:textFeild2.text]]; 160 | task2 = [operationSession dataTaskWithRequest:request2]; 161 | [task2 resume]; 162 | } 163 | 164 | } 165 | 166 | - (BOOL)_outputNodePlaying 167 | { 168 | UInt32 property = 0; 169 | UInt32 propertySize = sizeof(property); 170 | AudioUnitGetProperty(outputAudioUnit, kAudioOutputUnitProperty_IsRunning, kAudioUnitScope_Global, 0, &property, &propertySize); 171 | return property != 0; 172 | } 173 | 174 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler 175 | { 176 | completionHandler(NSURLSessionResponseAllow); 177 | } 178 | 179 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data 180 | { 181 | dispatch_async(dispatch_get_main_queue(), ^{ 182 | tip.text = @"receiving data..."; 183 | tip.textColor = UIColor.blackColor; 184 | firstComplete = YES; 185 | }); 186 | if ([dataTask isEqual:task1]) { 187 | [parser parseData:data]; 188 | } 189 | else if ([dataTask isEqual:task2]) { 190 | if (![self _outputNodePlaying] && firstComplete) { 191 | OSStatus aError = AUGraphStart(audioGraph); 192 | aError = AudioOutputUnitStart(outputAudioUnit); 193 | } 194 | [parser2 parseData:data]; 195 | } 196 | } 197 | 198 | - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 199 | { 200 | dispatch_async(dispatch_get_main_queue(), ^{ 201 | if (error) { 202 | tip.textColor = UIColor.redColor; 203 | tip.text = @"Fail"; 204 | textFeild.text = @""; 205 | [textFeild setEnabled:YES]; 206 | return; 207 | } 208 | tip.text = @""; 209 | }); 210 | } 211 | 212 | - (void)audioStreamParser:(SKAudioParser *)inParser didObtainStreamDescription:(AudioStreamBasicDescription *)inDescription 213 | { 214 | NSLog(@"mSampleRate: %f", inDescription->mSampleRate); 215 | NSLog(@"mFormatID: %u", (unsigned int)inDescription->mFormatID); 216 | NSLog(@"mFormatFlags: %u", (unsigned int)inDescription->mFormatFlags); 217 | NSLog(@"mBytesPerPacket: %u", (unsigned int)inDescription->mBytesPerPacket); 218 | NSLog(@"mFramesPerPacket: %u", (unsigned int)inDescription->mFramesPerPacket); 219 | NSLog(@"mBytesPerFrame: %u", (unsigned int)inDescription->mBytesPerFrame); 220 | NSLog(@"mChannelsPerFrame: %u", (unsigned int)inDescription->mChannelsPerFrame); 221 | NSLog(@"mBitsPerChannel: %u", (unsigned int)inDescription->mBitsPerChannel); 222 | NSLog(@"mReserved: %u", (unsigned int)inDescription->mReserved); 223 | 224 | if ([inParser isEqual:parser]) { 225 | converter = [[SKAudioConverter alloc] initWithSourceFormat:inDescription]; 226 | } 227 | else if ([inParser isEqual:parser2]) { 228 | converter2 = [[SKAudioConverter alloc] initWithSourceFormat:inDescription]; 229 | } 230 | } 231 | - (void)audioStreamParser:(SKAudioParser *)inParser packetData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount 232 | { 233 | if ([inParser isEqual:parser]) { 234 | [buffer storePacketData:inBytes dataLength:inLength packetDescriptions:inPacketDescriptions packetsCount:inPacketsCount]; 235 | } 236 | else if ([inParser isEqual:parser2]){ 237 | [buffer2 storePacketData:inBytes dataLength:inLength packetDescriptions:inPacketDescriptions packetsCount:inPacketsCount]; 238 | } 239 | } 240 | 241 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber 242 | { 243 | if (buffer.availablePacketCount < converter.packetsPerSecond * 4) { 244 | return -1; 245 | } 246 | return [converter requestNumberOfFrames:inNumberOfFrames ioData:inIoData busNumber:inBusNumber buffer:buffer]; 247 | } 248 | 249 | - (OSStatus)requestNumberOfFrames2:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber 250 | { 251 | if (buffer2.availablePacketCount < converter2.packetsPerSecond * 4) { 252 | return -1; 253 | } 254 | return [converter2 requestNumberOfFrames:inNumberOfFrames ioData:inIoData busNumber:inBusNumber buffer:buffer2]; 255 | } 256 | 257 | void MyAudioUnitPropertyListenerProc(void *inRefCon, AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope,AudioUnitElement inElement) 258 | { 259 | 260 | } 261 | 262 | static OSStatus RenderCallback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 263 | { 264 | ViewController *self = (__bridge ViewController *)userData; 265 | 266 | OSStatus status = [self requestNumberOfFrames:inNumberFrames ioData:ioData busNumber:inBusNumber]; 267 | 268 | return status; 269 | } 270 | 271 | static OSStatus RenderCallback2(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 272 | { 273 | ViewController *self = (__bridge ViewController *)userData; 274 | 275 | OSStatus status = [self requestNumberOfFrames2:inNumberFrames ioData:ioData busNumber:inBusNumber]; 276 | 277 | return status; 278 | } 279 | 280 | @end 281 | -------------------------------------------------------------------------------- /AudioUnitSample/MixPlaying/MixPlaying/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MixPlaying 4 | // 5 | // Created by StevenKuo on 2015/11/19. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StevenKuo/AudioUnitSample/b50c8111600d283cbde02ce48f1ae36b3aa49f61/AudioUnitSample/RemoteInput/.DS_Store -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9C7E4A971C0EA8ED008F91F2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7E4A961C0EA8ED008F91F2 /* main.m */; }; 11 | 9C7E4A9A1C0EA8ED008F91F2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7E4A991C0EA8ED008F91F2 /* AppDelegate.m */; }; 12 | 9C7E4A9D1C0EA8ED008F91F2 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7E4A9C1C0EA8ED008F91F2 /* ViewController.m */; }; 13 | 9C7E4AA01C0EA8ED008F91F2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C7E4A9E1C0EA8ED008F91F2 /* Main.storyboard */; }; 14 | 9C7E4AA21C0EA8ED008F91F2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9C7E4AA11C0EA8ED008F91F2 /* Assets.xcassets */; }; 15 | 9C7E4AA51C0EA8ED008F91F2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C7E4AA31C0EA8ED008F91F2 /* LaunchScreen.storyboard */; }; 16 | 9C7E4AB01C0EA93E008F91F2 /* SKAudioBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7E4AAD1C0EA93E008F91F2 /* SKAudioBuffer.m */; }; 17 | 9C7E4AB11C0EA93E008F91F2 /* SKAudioParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7E4AAF1C0EA93E008F91F2 /* SKAudioParser.m */; }; 18 | 9C7E4AB41C0EA970008F91F2 /* SKAudioConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7E4AB31C0EA970008F91F2 /* SKAudioConverter.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 9C7E4A921C0EA8ED008F91F2 /* RemoteInput.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RemoteInput.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 9C7E4A961C0EA8ED008F91F2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 24 | 9C7E4A981C0EA8ED008F91F2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 25 | 9C7E4A991C0EA8ED008F91F2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 26 | 9C7E4A9B1C0EA8ED008F91F2 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 27 | 9C7E4A9C1C0EA8ED008F91F2 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 28 | 9C7E4A9F1C0EA8ED008F91F2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 9C7E4AA11C0EA8ED008F91F2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 9C7E4AA41C0EA8ED008F91F2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 9C7E4AA61C0EA8ED008F91F2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 9C7E4AAC1C0EA93E008F91F2 /* SKAudioBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SKAudioBuffer.h; path = RemoteInput/SKAudioBuffer.h; sourceTree = ""; }; 33 | 9C7E4AAD1C0EA93E008F91F2 /* SKAudioBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SKAudioBuffer.m; path = RemoteInput/SKAudioBuffer.m; sourceTree = ""; }; 34 | 9C7E4AAE1C0EA93E008F91F2 /* SKAudioParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SKAudioParser.h; path = RemoteInput/SKAudioParser.h; sourceTree = ""; }; 35 | 9C7E4AAF1C0EA93E008F91F2 /* SKAudioParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SKAudioParser.m; path = RemoteInput/SKAudioParser.m; sourceTree = ""; }; 36 | 9C7E4AB21C0EA970008F91F2 /* SKAudioConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SKAudioConverter.h; path = RemoteInput/SKAudioConverter.h; sourceTree = ""; }; 37 | 9C7E4AB31C0EA970008F91F2 /* SKAudioConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SKAudioConverter.m; path = RemoteInput/SKAudioConverter.m; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | 9C7E4A8F1C0EA8ED008F91F2 /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 9C7E4A891C0EA8ED008F91F2 = { 52 | isa = PBXGroup; 53 | children = ( 54 | 9C7E4AB21C0EA970008F91F2 /* SKAudioConverter.h */, 55 | 9C7E4AB31C0EA970008F91F2 /* SKAudioConverter.m */, 56 | 9C7E4AAC1C0EA93E008F91F2 /* SKAudioBuffer.h */, 57 | 9C7E4AAD1C0EA93E008F91F2 /* SKAudioBuffer.m */, 58 | 9C7E4AAE1C0EA93E008F91F2 /* SKAudioParser.h */, 59 | 9C7E4AAF1C0EA93E008F91F2 /* SKAudioParser.m */, 60 | 9C7E4A941C0EA8ED008F91F2 /* RemoteInput */, 61 | 9C7E4A931C0EA8ED008F91F2 /* Products */, 62 | ); 63 | sourceTree = ""; 64 | }; 65 | 9C7E4A931C0EA8ED008F91F2 /* Products */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 9C7E4A921C0EA8ED008F91F2 /* RemoteInput.app */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | 9C7E4A941C0EA8ED008F91F2 /* RemoteInput */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 9C7E4A981C0EA8ED008F91F2 /* AppDelegate.h */, 77 | 9C7E4A991C0EA8ED008F91F2 /* AppDelegate.m */, 78 | 9C7E4A9B1C0EA8ED008F91F2 /* ViewController.h */, 79 | 9C7E4A9C1C0EA8ED008F91F2 /* ViewController.m */, 80 | 9C7E4A9E1C0EA8ED008F91F2 /* Main.storyboard */, 81 | 9C7E4AA11C0EA8ED008F91F2 /* Assets.xcassets */, 82 | 9C7E4AA31C0EA8ED008F91F2 /* LaunchScreen.storyboard */, 83 | 9C7E4AA61C0EA8ED008F91F2 /* Info.plist */, 84 | 9C7E4A951C0EA8ED008F91F2 /* Supporting Files */, 85 | ); 86 | path = RemoteInput; 87 | sourceTree = ""; 88 | }; 89 | 9C7E4A951C0EA8ED008F91F2 /* Supporting Files */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 9C7E4A961C0EA8ED008F91F2 /* main.m */, 93 | ); 94 | name = "Supporting Files"; 95 | sourceTree = ""; 96 | }; 97 | /* End PBXGroup section */ 98 | 99 | /* Begin PBXNativeTarget section */ 100 | 9C7E4A911C0EA8ED008F91F2 /* RemoteInput */ = { 101 | isa = PBXNativeTarget; 102 | buildConfigurationList = 9C7E4AA91C0EA8ED008F91F2 /* Build configuration list for PBXNativeTarget "RemoteInput" */; 103 | buildPhases = ( 104 | 9C7E4A8E1C0EA8ED008F91F2 /* Sources */, 105 | 9C7E4A8F1C0EA8ED008F91F2 /* Frameworks */, 106 | 9C7E4A901C0EA8ED008F91F2 /* Resources */, 107 | ); 108 | buildRules = ( 109 | ); 110 | dependencies = ( 111 | ); 112 | name = RemoteInput; 113 | productName = RemoteInput; 114 | productReference = 9C7E4A921C0EA8ED008F91F2 /* RemoteInput.app */; 115 | productType = "com.apple.product-type.application"; 116 | }; 117 | /* End PBXNativeTarget section */ 118 | 119 | /* Begin PBXProject section */ 120 | 9C7E4A8A1C0EA8ED008F91F2 /* Project object */ = { 121 | isa = PBXProject; 122 | attributes = { 123 | LastUpgradeCheck = 0710; 124 | ORGANIZATIONNAME = StevenKuo; 125 | TargetAttributes = { 126 | 9C7E4A911C0EA8ED008F91F2 = { 127 | CreatedOnToolsVersion = 7.1.1; 128 | DevelopmentTeam = Z48FVJQBYK; 129 | }; 130 | }; 131 | }; 132 | buildConfigurationList = 9C7E4A8D1C0EA8ED008F91F2 /* Build configuration list for PBXProject "RemoteInput" */; 133 | compatibilityVersion = "Xcode 3.2"; 134 | developmentRegion = English; 135 | hasScannedForEncodings = 0; 136 | knownRegions = ( 137 | en, 138 | Base, 139 | ); 140 | mainGroup = 9C7E4A891C0EA8ED008F91F2; 141 | productRefGroup = 9C7E4A931C0EA8ED008F91F2 /* Products */; 142 | projectDirPath = ""; 143 | projectRoot = ""; 144 | targets = ( 145 | 9C7E4A911C0EA8ED008F91F2 /* RemoteInput */, 146 | ); 147 | }; 148 | /* End PBXProject section */ 149 | 150 | /* Begin PBXResourcesBuildPhase section */ 151 | 9C7E4A901C0EA8ED008F91F2 /* Resources */ = { 152 | isa = PBXResourcesBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | 9C7E4AA51C0EA8ED008F91F2 /* LaunchScreen.storyboard in Resources */, 156 | 9C7E4AA21C0EA8ED008F91F2 /* Assets.xcassets in Resources */, 157 | 9C7E4AA01C0EA8ED008F91F2 /* Main.storyboard in Resources */, 158 | ); 159 | runOnlyForDeploymentPostprocessing = 0; 160 | }; 161 | /* End PBXResourcesBuildPhase section */ 162 | 163 | /* Begin PBXSourcesBuildPhase section */ 164 | 9C7E4A8E1C0EA8ED008F91F2 /* Sources */ = { 165 | isa = PBXSourcesBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | 9C7E4AB01C0EA93E008F91F2 /* SKAudioBuffer.m in Sources */, 169 | 9C7E4AB41C0EA970008F91F2 /* SKAudioConverter.m in Sources */, 170 | 9C7E4A9D1C0EA8ED008F91F2 /* ViewController.m in Sources */, 171 | 9C7E4A9A1C0EA8ED008F91F2 /* AppDelegate.m in Sources */, 172 | 9C7E4AB11C0EA93E008F91F2 /* SKAudioParser.m in Sources */, 173 | 9C7E4A971C0EA8ED008F91F2 /* main.m in Sources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXSourcesBuildPhase section */ 178 | 179 | /* Begin PBXVariantGroup section */ 180 | 9C7E4A9E1C0EA8ED008F91F2 /* Main.storyboard */ = { 181 | isa = PBXVariantGroup; 182 | children = ( 183 | 9C7E4A9F1C0EA8ED008F91F2 /* Base */, 184 | ); 185 | name = Main.storyboard; 186 | sourceTree = ""; 187 | }; 188 | 9C7E4AA31C0EA8ED008F91F2 /* LaunchScreen.storyboard */ = { 189 | isa = PBXVariantGroup; 190 | children = ( 191 | 9C7E4AA41C0EA8ED008F91F2 /* Base */, 192 | ); 193 | name = LaunchScreen.storyboard; 194 | sourceTree = ""; 195 | }; 196 | /* End PBXVariantGroup section */ 197 | 198 | /* Begin XCBuildConfiguration section */ 199 | 9C7E4AA71C0EA8ED008F91F2 /* Debug */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | ALWAYS_SEARCH_USER_PATHS = NO; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 204 | CLANG_CXX_LIBRARY = "libc++"; 205 | CLANG_ENABLE_MODULES = YES; 206 | CLANG_ENABLE_OBJC_ARC = YES; 207 | CLANG_WARN_BOOL_CONVERSION = YES; 208 | CLANG_WARN_CONSTANT_CONVERSION = YES; 209 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 210 | CLANG_WARN_EMPTY_BODY = YES; 211 | CLANG_WARN_ENUM_CONVERSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 214 | CLANG_WARN_UNREACHABLE_CODE = YES; 215 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 216 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 217 | COPY_PHASE_STRIP = NO; 218 | DEBUG_INFORMATION_FORMAT = dwarf; 219 | ENABLE_STRICT_OBJC_MSGSEND = YES; 220 | ENABLE_TESTABILITY = YES; 221 | GCC_C_LANGUAGE_STANDARD = gnu99; 222 | GCC_DYNAMIC_NO_PIC = NO; 223 | GCC_NO_COMMON_BLOCKS = YES; 224 | GCC_OPTIMIZATION_LEVEL = 0; 225 | GCC_PREPROCESSOR_DEFINITIONS = ( 226 | "DEBUG=1", 227 | "$(inherited)", 228 | ); 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 236 | MTL_ENABLE_DEBUG_INFO = YES; 237 | ONLY_ACTIVE_ARCH = YES; 238 | SDKROOT = iphoneos; 239 | TARGETED_DEVICE_FAMILY = "1,2"; 240 | }; 241 | name = Debug; 242 | }; 243 | 9C7E4AA81C0EA8ED008F91F2 /* Release */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 248 | CLANG_CXX_LIBRARY = "libc++"; 249 | CLANG_ENABLE_MODULES = YES; 250 | CLANG_ENABLE_OBJC_ARC = YES; 251 | CLANG_WARN_BOOL_CONVERSION = YES; 252 | CLANG_WARN_CONSTANT_CONVERSION = YES; 253 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 254 | CLANG_WARN_EMPTY_BODY = YES; 255 | CLANG_WARN_ENUM_CONVERSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 261 | COPY_PHASE_STRIP = NO; 262 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 263 | ENABLE_NS_ASSERTIONS = NO; 264 | ENABLE_STRICT_OBJC_MSGSEND = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu99; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 274 | MTL_ENABLE_DEBUG_INFO = NO; 275 | SDKROOT = iphoneos; 276 | TARGETED_DEVICE_FAMILY = "1,2"; 277 | VALIDATE_PRODUCT = YES; 278 | }; 279 | name = Release; 280 | }; 281 | 9C7E4AAA1C0EA8ED008F91F2 /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | CODE_SIGN_IDENTITY = "iPhone Developer"; 286 | INFOPLIST_FILE = RemoteInput/Info.plist; 287 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 288 | PRODUCT_BUNDLE_IDENTIFIER = SK.RemoteInput; 289 | PRODUCT_NAME = "$(TARGET_NAME)"; 290 | }; 291 | name = Debug; 292 | }; 293 | 9C7E4AAB1C0EA8ED008F91F2 /* Release */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 297 | CODE_SIGN_IDENTITY = "iPhone Developer"; 298 | INFOPLIST_FILE = RemoteInput/Info.plist; 299 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 300 | PRODUCT_BUNDLE_IDENTIFIER = SK.RemoteInput; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | }; 303 | name = Release; 304 | }; 305 | /* End XCBuildConfiguration section */ 306 | 307 | /* Begin XCConfigurationList section */ 308 | 9C7E4A8D1C0EA8ED008F91F2 /* Build configuration list for PBXProject "RemoteInput" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | 9C7E4AA71C0EA8ED008F91F2 /* Debug */, 312 | 9C7E4AA81C0EA8ED008F91F2 /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | defaultConfigurationName = Release; 316 | }; 317 | 9C7E4AA91C0EA8ED008F91F2 /* Build configuration list for PBXNativeTarget "RemoteInput" */ = { 318 | isa = XCConfigurationList; 319 | buildConfigurations = ( 320 | 9C7E4AAA1C0EA8ED008F91F2 /* Debug */, 321 | 9C7E4AAB1C0EA8ED008F91F2 /* Release */, 322 | ); 323 | defaultConfigurationIsVisible = 0; 324 | }; 325 | /* End XCConfigurationList section */ 326 | }; 327 | rootObject = 9C7E4A8A1C0EA8ED008F91F2 /* Project object */; 328 | } 329 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RemoteInput 4 | // 5 | // Created by StevenKuo on 2015/12/2. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // RemoteInput 4 | // 5 | // Created by StevenKuo on 2015/12/2. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/Assets.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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 40 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSExceptionDomains 8 | 9 | s3-us-west-2.amazonaws.com 10 | 11 | NSExceptionRequiresForwardSecrecy 12 | 13 | NSIncludesSubdomains 14 | 15 | 16 | 17 | 18 | CFBundleDevelopmentRegion 19 | en 20 | CFBundleExecutable 21 | $(EXECUTABLE_NAME) 22 | CFBundleIdentifier 23 | $(PRODUCT_BUNDLE_IDENTIFIER) 24 | CFBundleInfoDictionaryVersion 25 | 6.0 26 | CFBundleName 27 | $(PRODUCT_NAME) 28 | CFBundlePackageType 29 | APPL 30 | CFBundleShortVersionString 31 | 1.0 32 | CFBundleSignature 33 | ???? 34 | CFBundleVersion 35 | 1 36 | LSRequiresIPhoneOS 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIMainStoryboardFile 41 | Main 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/SKAudioBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioBuffer.h 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef struct { 13 | AudioStreamPacketDescription packetDescription; 14 | void *data; 15 | } AudioPacketInfo; 16 | 17 | @class SKAudioBuffer; 18 | 19 | @protocol SKAudioBufferDelegate 20 | 21 | - (AudioStreamBasicDescription)usedAudioStreamBasicDescription; 22 | - (void)audioBufferDidBeginReadPacket:(SKAudioBuffer *)inBuffer; 23 | @end 24 | 25 | @interface SKAudioBuffer : NSObject 26 | { 27 | __weak id delegate; 28 | 29 | AudioPacketInfo *packets; 30 | size_t packetWriteIndex; 31 | size_t packetReadIndex; 32 | size_t packetCount; 33 | 34 | NSMutableData *audioData; 35 | NSMutableData *packetDescData; 36 | NSUInteger packetReadHead; 37 | NSUInteger readPacketIndex; 38 | } 39 | 40 | 41 | - (void)storePacketData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount; 42 | - (void)movePacketReadIndex; 43 | 44 | @property (readonly, nonatomic) size_t availablePacketCount; 45 | @property (weak, nonatomic) id delegate; 46 | @property (readonly, nonatomic) AudioPacketInfo currentPacketInfo; 47 | @end 48 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/SKAudioBuffer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioBuffer.m 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import "SKAudioBuffer.h" 10 | 11 | @implementation SKAudioBuffer 12 | 13 | - (id)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | 18 | packetCount = 2048; 19 | packets = (AudioPacketInfo *)calloc(packetCount, sizeof(AudioPacketInfo)); 20 | 21 | audioData = [[NSMutableData alloc] init]; 22 | packetDescData = [[NSMutableData alloc] init]; 23 | } 24 | return self; 25 | } 26 | 27 | 28 | - (void)storePacketData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount 29 | { 30 | // for (NSUInteger packetIndex = 0; packetIndex < inPacketsCount ; packetIndex ++) { 31 | // inPacketDescriptions[packetIndex].mStartOffset += audioData.length; 32 | // } 33 | // 34 | // @synchronized (self) { 35 | // [audioData appendBytes:inBytes length:inLength]; 36 | // [packetDescData appendBytes:inPacketDescriptions length:sizeof(AudioStreamPacketDescription) * inPacketsCount]; 37 | // availablePacketCount += inPacketsCount; 38 | // } 39 | 40 | @synchronized (self) { 41 | 42 | for (size_t index = 0; index < inPacketsCount; index ++) { 43 | 44 | if (packetWriteIndex >= packetCount) { 45 | size_t oldSize = packetCount * sizeof(AudioPacketInfo); 46 | packetCount = packetCount * 2; 47 | packets = (AudioPacketInfo *)realloc(packets, packetCount * sizeof(AudioPacketInfo)); 48 | bzero((void *)packets + oldSize, oldSize); 49 | } 50 | AudioStreamPacketDescription emptyDescription; 51 | 52 | if (!inPacketDescriptions) { 53 | emptyDescription.mStartOffset = index; 54 | emptyDescription.mDataByteSize = 1; 55 | emptyDescription.mVariableFramesInPacket = 0; 56 | } 57 | 58 | AudioStreamPacketDescription *currentDescription = inPacketDescriptions ? &(inPacketDescriptions[index]) : &emptyDescription; 59 | 60 | AudioPacketInfo *nextInfo = &packets[packetWriteIndex]; 61 | if (nextInfo->data) { 62 | free(nextInfo->data); 63 | nextInfo->data = NULL; 64 | } 65 | nextInfo->data = malloc(currentDescription->mDataByteSize); 66 | NSAssert(nextInfo->data, @"Must allocate memory for current packet"); 67 | memcpy(nextInfo->data, inBytes + currentDescription->mStartOffset, currentDescription->mDataByteSize); 68 | memcpy(&nextInfo->packetDescription, currentDescription, sizeof(AudioStreamPacketDescription)); 69 | 70 | packetWriteIndex++; 71 | 72 | _availablePacketCount++; 73 | } 74 | } 75 | } 76 | 77 | - (void)setPacketReadIndex:(size_t)inNewIndex 78 | { 79 | size_t max = _availablePacketCount; 80 | 81 | if (inNewIndex > max) { 82 | packetReadIndex = max; 83 | return; 84 | } 85 | 86 | if (inNewIndex < packetWriteIndex) { 87 | packetReadIndex = inNewIndex; 88 | } 89 | else { 90 | packetReadIndex = packetWriteIndex; 91 | } 92 | } 93 | 94 | - (void)movePacketReadIndex 95 | { 96 | [self setPacketReadIndex:packetReadIndex + 1]; 97 | } 98 | 99 | - (AudioPacketInfo)currentPacketInfo 100 | { 101 | // @synchronized (self) { 102 | // if (readPacketIndex >= availablePacketCount) { 103 | // inCallback(nil, 0, nil, YES); 104 | // return; 105 | // } 106 | // if (readPacketIndex == 0) { 107 | // [delegate audioBufferDidBeginReadPacket:self]; 108 | // } 109 | // 110 | // AudioStreamPacketDescription* packetDescriptions = (AudioStreamPacketDescription* )packetDescData.bytes; 111 | // 112 | // AudioPacketInfo *packet = (AudioPacketInfo *)calloc(1, sizeof(AudioPacketInfo)); 113 | // packet->data = malloc(packetDescriptions[readPacketIndex].mDataByteSize); 114 | // memcpy(packet->data, audioData.bytes + packetDescriptions[readPacketIndex].mStartOffset, packetDescriptions[readPacketIndex].mDataByteSize); 115 | // memcpy(&packet->packetDescription, &packetDescriptions[readPacketIndex], sizeof(AudioStreamPacketDescription)); 116 | // 117 | // readPacketIndex ++; 118 | // 119 | // return *packet; 120 | // } 121 | return packets[packetReadIndex]; 122 | } 123 | 124 | @synthesize delegate; 125 | @synthesize currentPacketInfo; 126 | @end 127 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/SKAudioConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioConverter.h 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SKAudioBuffer.h" 12 | 13 | @interface SKAudioConverter : NSObject 14 | { 15 | AudioStreamBasicDescription audioStreamDescription; 16 | AudioStreamBasicDescription destFormat; 17 | AudioConverterRef converter; 18 | AudioBufferList *renderBufferList; 19 | UInt32 renderBufferSize; 20 | } 21 | 22 | AudioStreamBasicDescription LinearPCMStreamDescription(); 23 | 24 | - (instancetype)initWithSourceFormat:(AudioStreamBasicDescription *)sourceFormat; 25 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber buffer:(SKAudioBuffer *)inBuffer; 26 | 27 | - (void)_fillBufferlist:(AudioBufferList *)ioData withBuffer:(SKAudioBuffer *)buffer packetDescription:(AudioStreamPacketDescription** )outDataPacketDescription; 28 | @property (readonly, nonatomic) double packetsPerSecond; 29 | @end 30 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/SKAudioConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioConverter.m 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "SKAudioConverter.h" 10 | 11 | static OSStatus AudioConverterFiller(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData); 12 | 13 | OSStatus AudioConverterFiller (AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) 14 | { 15 | NSArray *args = (__bridge NSArray *)inUserData; 16 | SKAudioConverter *self = args[0]; 17 | SKAudioBuffer *buffer = args[1]; 18 | // *ioNumberDataPackets = 1; 19 | [self _fillBufferlist:ioData withBuffer:buffer packetDescription:outDataPacketDescription]; 20 | return noErr; 21 | } 22 | 23 | AudioStreamBasicDescription LinearPCMStreamDescription() 24 | { 25 | AudioStreamBasicDescription destFormat; 26 | bzero(&destFormat, sizeof(AudioStreamBasicDescription)); 27 | destFormat.mSampleRate = 44100.0; 28 | destFormat.mFormatID = kAudioFormatLinearPCM; 29 | destFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; 30 | 31 | destFormat.mFramesPerPacket = 1; 32 | destFormat.mBytesPerPacket = 4; 33 | destFormat.mBytesPerFrame = 4; 34 | destFormat.mChannelsPerFrame = 2; 35 | destFormat.mBitsPerChannel = 16; 36 | destFormat.mReserved = 0; 37 | return destFormat; 38 | } 39 | 40 | @implementation SKAudioConverter 41 | 42 | - (instancetype)initWithSourceFormat:(AudioStreamBasicDescription *)sourceFormat 43 | { 44 | self = [super init]; 45 | if (self) { 46 | audioStreamDescription = *sourceFormat; 47 | destFormat = LinearPCMStreamDescription(); 48 | AudioConverterNew(&audioStreamDescription, &destFormat, &converter); 49 | 50 | UInt32 packetSize = 44100 * 4; 51 | renderBufferSize = packetSize; 52 | renderBufferList = (AudioBufferList *)calloc(1, sizeof(UInt32) + sizeof(AudioBuffer)); 53 | renderBufferList->mNumberBuffers = 1; 54 | renderBufferList->mBuffers[0].mNumberChannels = 2; 55 | renderBufferList->mBuffers[0].mDataByteSize = packetSize; 56 | renderBufferList->mBuffers[0].mData = calloc(1, packetSize); 57 | } 58 | return self; 59 | } 60 | 61 | - (void)_fillBufferlist:(AudioBufferList *)ioData withBuffer:(SKAudioBuffer *)buffer packetDescription:(AudioStreamPacketDescription** )outDataPacketDescription 62 | { 63 | static AudioStreamPacketDescription aspdesc; 64 | 65 | AudioPacketInfo currentPacketInfo = buffer.currentPacketInfo; 66 | 67 | void *data = currentPacketInfo.data; 68 | UInt32 length = (UInt32)currentPacketInfo.packetDescription.mDataByteSize; 69 | ioData->mBuffers[0].mData = data; 70 | ioData->mBuffers[0].mDataByteSize = length; 71 | ioData->mNumberBuffers = 1; 72 | 73 | *outDataPacketDescription = &aspdesc; 74 | aspdesc.mDataByteSize = length; 75 | aspdesc.mStartOffset = 0; 76 | aspdesc.mVariableFramesInPacket = 1; 77 | 78 | [buffer movePacketReadIndex]; 79 | } 80 | 81 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber buffer:(SKAudioBuffer *)inBuffer 82 | { 83 | UInt32 packetSize = inNumberOfFrames; 84 | NSArray *args = @[self, inBuffer]; 85 | OSStatus status = noErr; 86 | 87 | status = AudioConverterFillComplexBuffer(converter, AudioConverterFiller, (__bridge void *)(args), &packetSize, renderBufferList, NULL); 88 | 89 | if (noErr == status && packetSize) { 90 | inIoData->mNumberBuffers = 1; 91 | inIoData->mBuffers[0].mNumberChannels = 2; 92 | inIoData->mBuffers[0].mDataByteSize = renderBufferList->mBuffers[0].mDataByteSize; 93 | inIoData->mBuffers[0].mData = renderBufferList->mBuffers[0].mData; 94 | status = noErr; 95 | } 96 | return status; 97 | } 98 | 99 | - (double)packetsPerSecond 100 | { 101 | if (!(audioStreamDescription.mFramesPerPacket > 0)) { 102 | return 0; 103 | } 104 | return audioStreamDescription.mSampleRate / audioStreamDescription.mFramesPerPacket; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/SKAudioParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioParser.h 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class SKAudioParser; 13 | 14 | @protocol SKAudioParserDelegate 15 | 16 | - (void)audioStreamParser:(SKAudioParser *)inParser didObtainStreamDescription:(AudioStreamBasicDescription *)inDescription; 17 | - (void)audioStreamParser:(SKAudioParser *)inParser packetData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount; 18 | 19 | @end 20 | 21 | @interface SKAudioParser : NSObject 22 | { 23 | AudioFileStreamID audioFileStreamID; 24 | __weak id delegate; 25 | } 26 | 27 | - (void)parseData:(NSData *)inData; 28 | 29 | @property (weak, nonatomic) id delegate; 30 | @end 31 | 32 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/SKAudioParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioParser.m 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import "SKAudioParser.h" 10 | 11 | @implementation SKAudioParser 12 | 13 | 14 | void audioFileStreamPropertyListenerProc(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags) 15 | { 16 | /* 17 | kAudioFileStreamProperty_ReadyToProducePackets = 'redy', 18 | kAudioFileStreamProperty_FileFormat = 'ffmt', 19 | kAudioFileStreamProperty_DataFormat = 'dfmt', 20 | kAudioFileStreamProperty_FormatList = 'flst', 21 | kAudioFileStreamProperty_MagicCookieData = 'mgic', 22 | kAudioFileStreamProperty_AudioDataByteCount = 'bcnt', 23 | kAudioFileStreamProperty_AudioDataPacketCount = 'pcnt', 24 | kAudioFileStreamProperty_MaximumPacketSize = 'psze', 25 | kAudioFileStreamProperty_DataOffset = 'doff', 26 | kAudioFileStreamProperty_ChannelLayout = 'cmap', 27 | kAudioFileStreamProperty_PacketToFrame = 'pkfr', 28 | kAudioFileStreamProperty_FrameToPacket = 'frpk', 29 | kAudioFileStreamProperty_PacketToByte = 'pkby', 30 | kAudioFileStreamProperty_ByteToPacket = 'bypk', 31 | kAudioFileStreamProperty_PacketTableInfo = 'pnfo', 32 | kAudioFileStreamProperty_PacketSizeUpperBound = 'pkub', 33 | kAudioFileStreamProperty_AverageBytesPerPacket = 'abpp', 34 | kAudioFileStreamProperty_BitRate = 'brat', 35 | kAudioFileStreamProperty_InfoDictionary = 'info' 36 | */ 37 | if (inPropertyID == 'dfmt') { 38 | AudioStreamBasicDescription description; 39 | UInt32 descriptionSize = sizeof(description); 40 | AudioFileStreamGetProperty(inAudioFileStream, inPropertyID, &descriptionSize, &description); 41 | [((__bridge SKAudioParser *)inClientData).delegate audioStreamParser:(__bridge SKAudioParser *)inClientData didObtainStreamDescription:&description]; 42 | } 43 | } 44 | 45 | 46 | void audioFileStreamPacketsProc(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions) 47 | { 48 | [((__bridge SKAudioParser *)inClientData).delegate audioStreamParser:((__bridge SKAudioParser *)inClientData) packetData:inInputData dataLength:inNumberBytes packetDescriptions:inPacketDescriptions packetsCount:inNumberPackets]; 49 | 50 | } 51 | 52 | - (id)init 53 | { 54 | self = [super init]; 55 | if (self) { 56 | 57 | AudioFileStreamOpen((__bridge void *)(self), audioFileStreamPropertyListenerProc, audioFileStreamPacketsProc, kAudioFileMP3Type, &audioFileStreamID); 58 | 59 | } 60 | return self; 61 | } 62 | 63 | - (void)parseData:(NSData *)inData 64 | { 65 | AudioFileStreamParseBytes(audioFileStreamID, (UInt32)[inData length], [inData bytes], 0); 66 | } 67 | 68 | @synthesize delegate; 69 | @end 70 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // RemoteInput 4 | // 5 | // Created by StevenKuo on 2015/12/2. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // RemoteInput 4 | // 5 | // Created by StevenKuo on 2015/12/2. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import 12 | 13 | #import "SKAudioParser.h" 14 | #import "SKAudioBuffer.h" 15 | #import "SKAudioConverter.h" 16 | 17 | @interface ViewController () 18 | { 19 | AUGraph audioGraph; 20 | AUNode mixNode; 21 | AudioUnit mixAudioUnit; 22 | AUNode remoteIONode; 23 | AudioUnit remoteIOAudioUnit; 24 | 25 | SKAudioParser *parser; 26 | SKAudioBuffer *buffer; 27 | 28 | SKAudioConverter *converter; 29 | IBOutlet UITextField *textFeild; 30 | IBOutlet UILabel *tip; 31 | } 32 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber; 33 | @end 34 | 35 | 36 | static void MyAudioUnitPropertyListenerProc(void *inRefCon, AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope,AudioUnitElement inElement); 37 | 38 | static OSStatus RenderCallback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); 39 | 40 | @implementation ViewController 41 | 42 | - (id)initWithCoder:(NSCoder *)aDecoder 43 | { 44 | self = [super initWithCoder:aDecoder]; 45 | if (self) { 46 | 47 | parser = [[SKAudioParser alloc] init]; 48 | parser.delegate = self; 49 | 50 | buffer = [[SKAudioBuffer alloc] init]; 51 | 52 | OSStatus status = noErr; 53 | status = NewAUGraph(&audioGraph); 54 | status = AUGraphOpen(audioGraph); 55 | 56 | AudioComponentDescription outputUnitDescription = [self outputUnitDescription]; 57 | status = AUGraphAddNode(audioGraph, &outputUnitDescription, &remoteIONode); 58 | status = AUGraphNodeInfo(audioGraph, remoteIONode, &outputUnitDescription, &remoteIOAudioUnit); 59 | UInt32 maxFPS = 4096; 60 | status = AudioUnitSetProperty(remoteIOAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0,&maxFPS, sizeof(maxFPS)); 61 | 62 | AudioComponentDescription mixUnitDescription = [self mixUnitDescription]; 63 | status = AUGraphAddNode(audioGraph, &mixUnitDescription, &mixNode); 64 | status = AUGraphNodeInfo(audioGraph, mixNode, &mixUnitDescription, &mixAudioUnit); 65 | status = AudioUnitSetProperty(mixAudioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0,&maxFPS, sizeof(maxFPS)); 66 | 67 | status = AUGraphConnectNodeInput(audioGraph, mixNode, 0, remoteIONode, 0); 68 | status = AUGraphConnectNodeInput(audioGraph, remoteIONode, 1, mixNode, 1); 69 | status = AUGraphConnectNodeInput(audioGraph, mixNode, 1, remoteIONode, 0); 70 | 71 | AudioStreamBasicDescription destFormat = LinearPCMStreamDescription(); 72 | 73 | UInt32 oneFlag = 1; 74 | UInt32 busOne = 1; 75 | status = AudioUnitSetProperty(remoteIOAudioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, busOne, &oneFlag, sizeof(oneFlag)); 76 | 77 | 78 | status = AudioUnitSetProperty(remoteIOAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &destFormat, sizeof(destFormat)); 79 | 80 | status = AudioUnitSetProperty(remoteIOAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &destFormat, sizeof(destFormat)); 81 | 82 | status = AudioUnitSetProperty(mixAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &destFormat, sizeof(destFormat)); 83 | 84 | status = AudioUnitSetProperty(mixAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &destFormat, sizeof(destFormat)); 85 | 86 | 87 | 88 | status = AudioUnitSetParameter(mixAudioUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, 0.3, 0); 89 | 90 | 91 | status = AudioUnitAddPropertyListener(remoteIOAudioUnit, kAudioOutputUnitProperty_IsRunning, MyAudioUnitPropertyListenerProc, (__bridge void *)(self)); 92 | 93 | AURenderCallbackStruct callbackStruct; 94 | callbackStruct.inputProcRefCon = (__bridge void *)(self); 95 | callbackStruct.inputProc = RenderCallback; 96 | status = AUGraphSetNodeInputCallback(audioGraph, mixNode, 0, &callbackStruct); 97 | 98 | status = AUGraphInitialize(audioGraph); 99 | 100 | CAShow(audioGraph); 101 | AudioOutputUnitStop(remoteIOAudioUnit); 102 | } 103 | return self; 104 | } 105 | 106 | - (AudioComponentDescription)mixUnitDescription 107 | { 108 | AudioComponentDescription mixerUnitDescription; 109 | bzero(&mixerUnitDescription, sizeof(AudioComponentDescription)); 110 | mixerUnitDescription.componentType = kAudioUnitType_Mixer; 111 | mixerUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer; 112 | mixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 113 | mixerUnitDescription.componentFlags = 0; 114 | mixerUnitDescription.componentFlagsMask = 0; 115 | return mixerUnitDescription; 116 | } 117 | 118 | - (AudioComponentDescription)outputUnitDescription 119 | { 120 | AudioComponentDescription outputUnitDescription; 121 | bzero(&outputUnitDescription, sizeof(AudioComponentDescription)); 122 | outputUnitDescription.componentType = kAudioUnitType_Output; 123 | outputUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO; 124 | outputUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 125 | outputUnitDescription.componentFlags = 0; 126 | outputUnitDescription.componentFlagsMask = 0; 127 | return outputUnitDescription; 128 | } 129 | 130 | - (void)viewDidLoad { 131 | [super viewDidLoad]; 132 | OSStatus aError = AUGraphStart(audioGraph); 133 | aError = AudioOutputUnitStart(remoteIOAudioUnit); 134 | } 135 | 136 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 137 | [textFeild resignFirstResponder]; 138 | [textFeild setEnabled:NO]; 139 | return YES; 140 | } 141 | 142 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler 143 | { 144 | dispatch_async(dispatch_get_main_queue(), ^{ 145 | tip.text = @"receiving data..."; 146 | tip.textColor = UIColor.blackColor; 147 | }); 148 | completionHandler(NSURLSessionResponseAllow); 149 | } 150 | 151 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data 152 | { 153 | [parser parseData:data]; 154 | } 155 | 156 | - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 157 | { 158 | dispatch_async(dispatch_get_main_queue(), ^{ 159 | if (error) { 160 | tip.textColor = UIColor.redColor; 161 | tip.text = @"Fail"; 162 | textFeild.text = @""; 163 | [textFeild setEnabled:YES]; 164 | return; 165 | } 166 | tip.text = @""; 167 | }); 168 | } 169 | 170 | - (void)textFieldDidEndEditing:(UITextField *)textField { 171 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 172 | NSURLSessionConfiguration *myConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; 173 | NSURLSession *operationSession = [NSURLSession sessionWithConfiguration:myConfiguration delegate:(id)self delegateQueue:operationQueue]; 174 | 175 | NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:textFeild.text]]; 176 | NSURLSessionDataTask *task = [operationSession dataTaskWithRequest:request]; 177 | [task resume]; 178 | } 179 | 180 | 181 | - (void)audioStreamParser:(SKAudioParser *)inParser didObtainStreamDescription:(AudioStreamBasicDescription *)inDescription 182 | { 183 | NSLog(@"mSampleRate: %f", inDescription->mSampleRate); 184 | NSLog(@"mFormatID: %u", (unsigned int)inDescription->mFormatID); 185 | NSLog(@"mFormatFlags: %u", (unsigned int)inDescription->mFormatFlags); 186 | NSLog(@"mBytesPerPacket: %u", (unsigned int)inDescription->mBytesPerPacket); 187 | NSLog(@"mFramesPerPacket: %u", (unsigned int)inDescription->mFramesPerPacket); 188 | NSLog(@"mBytesPerFrame: %u", (unsigned int)inDescription->mBytesPerFrame); 189 | NSLog(@"mChannelsPerFrame: %u", (unsigned int)inDescription->mChannelsPerFrame); 190 | NSLog(@"mBitsPerChannel: %u", (unsigned int)inDescription->mBitsPerChannel); 191 | NSLog(@"mReserved: %u", (unsigned int)inDescription->mReserved); 192 | 193 | converter = [[SKAudioConverter alloc] initWithSourceFormat:inDescription]; 194 | } 195 | - (void)audioStreamParser:(SKAudioParser *)inParser packetData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount 196 | { 197 | [buffer storePacketData:inBytes dataLength:inLength packetDescriptions:inPacketDescriptions packetsCount:inPacketsCount]; 198 | } 199 | 200 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber 201 | { 202 | if (buffer.availablePacketCount < converter.packetsPerSecond * 4) { 203 | return -1; 204 | } 205 | return [converter requestNumberOfFrames:inNumberOfFrames ioData:inIoData busNumber:inBusNumber buffer:buffer]; 206 | } 207 | 208 | void MyAudioUnitPropertyListenerProc(void *inRefCon, AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope,AudioUnitElement inElement) 209 | { 210 | 211 | } 212 | 213 | static OSStatus RenderCallback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 214 | { 215 | ViewController *self = (__bridge ViewController *)userData; 216 | 217 | OSStatus status = [self requestNumberOfFrames:inNumberFrames ioData:ioData busNumber:inBusNumber]; 218 | 219 | return status; 220 | } 221 | 222 | @end 223 | -------------------------------------------------------------------------------- /AudioUnitSample/RemoteInput/RemoteInput/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RemoteInput 4 | // 5 | // Created by StevenKuo on 2015/12/2. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StevenKuo/AudioUnitSample/b50c8111600d283cbde02ce48f1ae36b3aa49f61/AudioUnitSample/SimplePlaying/.DS_Store -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9C10C3FD1BF34592001FE535 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C10C3FC1BF34592001FE535 /* main.m */; }; 11 | 9C10C4001BF34592001FE535 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C10C3FF1BF34592001FE535 /* AppDelegate.m */; }; 12 | 9C10C4031BF34592001FE535 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C10C4021BF34592001FE535 /* ViewController.m */; }; 13 | 9C10C4061BF34592001FE535 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C10C4041BF34592001FE535 /* Main.storyboard */; }; 14 | 9C10C4081BF34592001FE535 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9C10C4071BF34592001FE535 /* Assets.xcassets */; }; 15 | 9C10C40B1BF34592001FE535 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C10C4091BF34592001FE535 /* LaunchScreen.storyboard */; }; 16 | 9C10C4161BF347A7001FE535 /* SKAudioBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C10C4131BF347A7001FE535 /* SKAudioBuffer.m */; }; 17 | 9C10C4171BF347A7001FE535 /* SKAudioParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C10C4151BF347A7001FE535 /* SKAudioParser.m */; }; 18 | 9C10C41A1BF347E5001FE535 /* SKAudioConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C10C4191BF347E5001FE535 /* SKAudioConverter.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 9C10C3F81BF34592001FE535 /* SimplePlaying.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SimplePlaying.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 9C10C3FC1BF34592001FE535 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 24 | 9C10C3FE1BF34592001FE535 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 25 | 9C10C3FF1BF34592001FE535 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 26 | 9C10C4011BF34592001FE535 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 27 | 9C10C4021BF34592001FE535 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 28 | 9C10C4051BF34592001FE535 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 9C10C4071BF34592001FE535 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 9C10C40A1BF34592001FE535 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 9C10C40C1BF34592001FE535 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 9C10C4121BF347A7001FE535 /* SKAudioBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SKAudioBuffer.h; sourceTree = ""; }; 33 | 9C10C4131BF347A7001FE535 /* SKAudioBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKAudioBuffer.m; sourceTree = ""; }; 34 | 9C10C4141BF347A7001FE535 /* SKAudioParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SKAudioParser.h; sourceTree = ""; }; 35 | 9C10C4151BF347A7001FE535 /* SKAudioParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKAudioParser.m; sourceTree = ""; }; 36 | 9C10C4181BF347E5001FE535 /* SKAudioConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SKAudioConverter.h; sourceTree = ""; }; 37 | 9C10C4191BF347E5001FE535 /* SKAudioConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKAudioConverter.m; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | 9C10C3F51BF34592001FE535 /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 9C10C3EF1BF34592001FE535 = { 52 | isa = PBXGroup; 53 | children = ( 54 | 9C10C3FA1BF34592001FE535 /* SimplePlaying */, 55 | 9C10C3F91BF34592001FE535 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | 9C10C3F91BF34592001FE535 /* Products */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | 9C10C3F81BF34592001FE535 /* SimplePlaying.app */, 63 | ); 64 | name = Products; 65 | sourceTree = ""; 66 | }; 67 | 9C10C3FA1BF34592001FE535 /* SimplePlaying */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 9C10C4181BF347E5001FE535 /* SKAudioConverter.h */, 71 | 9C10C4191BF347E5001FE535 /* SKAudioConverter.m */, 72 | 9C10C4121BF347A7001FE535 /* SKAudioBuffer.h */, 73 | 9C10C4131BF347A7001FE535 /* SKAudioBuffer.m */, 74 | 9C10C4141BF347A7001FE535 /* SKAudioParser.h */, 75 | 9C10C4151BF347A7001FE535 /* SKAudioParser.m */, 76 | 9C10C3FE1BF34592001FE535 /* AppDelegate.h */, 77 | 9C10C3FF1BF34592001FE535 /* AppDelegate.m */, 78 | 9C10C4011BF34592001FE535 /* ViewController.h */, 79 | 9C10C4021BF34592001FE535 /* ViewController.m */, 80 | 9C10C4041BF34592001FE535 /* Main.storyboard */, 81 | 9C10C4071BF34592001FE535 /* Assets.xcassets */, 82 | 9C10C4091BF34592001FE535 /* LaunchScreen.storyboard */, 83 | 9C10C40C1BF34592001FE535 /* Info.plist */, 84 | 9C10C3FB1BF34592001FE535 /* Supporting Files */, 85 | ); 86 | path = SimplePlaying; 87 | sourceTree = ""; 88 | }; 89 | 9C10C3FB1BF34592001FE535 /* Supporting Files */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 9C10C3FC1BF34592001FE535 /* main.m */, 93 | ); 94 | name = "Supporting Files"; 95 | sourceTree = ""; 96 | }; 97 | /* End PBXGroup section */ 98 | 99 | /* Begin PBXNativeTarget section */ 100 | 9C10C3F71BF34592001FE535 /* SimplePlaying */ = { 101 | isa = PBXNativeTarget; 102 | buildConfigurationList = 9C10C40F1BF34592001FE535 /* Build configuration list for PBXNativeTarget "SimplePlaying" */; 103 | buildPhases = ( 104 | 9C10C3F41BF34592001FE535 /* Sources */, 105 | 9C10C3F51BF34592001FE535 /* Frameworks */, 106 | 9C10C3F61BF34592001FE535 /* Resources */, 107 | ); 108 | buildRules = ( 109 | ); 110 | dependencies = ( 111 | ); 112 | name = SimplePlaying; 113 | productName = SimplePlaying; 114 | productReference = 9C10C3F81BF34592001FE535 /* SimplePlaying.app */; 115 | productType = "com.apple.product-type.application"; 116 | }; 117 | /* End PBXNativeTarget section */ 118 | 119 | /* Begin PBXProject section */ 120 | 9C10C3F01BF34592001FE535 /* Project object */ = { 121 | isa = PBXProject; 122 | attributes = { 123 | LastUpgradeCheck = 0710; 124 | ORGANIZATIONNAME = StevenKuo; 125 | TargetAttributes = { 126 | 9C10C3F71BF34592001FE535 = { 127 | CreatedOnToolsVersion = 7.1; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = 9C10C3F31BF34592001FE535 /* Build configuration list for PBXProject "SimplePlaying" */; 132 | compatibilityVersion = "Xcode 3.2"; 133 | developmentRegion = English; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = 9C10C3EF1BF34592001FE535; 140 | productRefGroup = 9C10C3F91BF34592001FE535 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | 9C10C3F71BF34592001FE535 /* SimplePlaying */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXResourcesBuildPhase section */ 150 | 9C10C3F61BF34592001FE535 /* Resources */ = { 151 | isa = PBXResourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | 9C10C40B1BF34592001FE535 /* LaunchScreen.storyboard in Resources */, 155 | 9C10C4081BF34592001FE535 /* Assets.xcassets in Resources */, 156 | 9C10C4061BF34592001FE535 /* Main.storyboard in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXSourcesBuildPhase section */ 163 | 9C10C3F41BF34592001FE535 /* Sources */ = { 164 | isa = PBXSourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | 9C10C4161BF347A7001FE535 /* SKAudioBuffer.m in Sources */, 168 | 9C10C41A1BF347E5001FE535 /* SKAudioConverter.m in Sources */, 169 | 9C10C4031BF34592001FE535 /* ViewController.m in Sources */, 170 | 9C10C4001BF34592001FE535 /* AppDelegate.m in Sources */, 171 | 9C10C4171BF347A7001FE535 /* SKAudioParser.m in Sources */, 172 | 9C10C3FD1BF34592001FE535 /* main.m in Sources */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXSourcesBuildPhase section */ 177 | 178 | /* Begin PBXVariantGroup section */ 179 | 9C10C4041BF34592001FE535 /* Main.storyboard */ = { 180 | isa = PBXVariantGroup; 181 | children = ( 182 | 9C10C4051BF34592001FE535 /* Base */, 183 | ); 184 | name = Main.storyboard; 185 | sourceTree = ""; 186 | }; 187 | 9C10C4091BF34592001FE535 /* LaunchScreen.storyboard */ = { 188 | isa = PBXVariantGroup; 189 | children = ( 190 | 9C10C40A1BF34592001FE535 /* Base */, 191 | ); 192 | name = LaunchScreen.storyboard; 193 | sourceTree = ""; 194 | }; 195 | /* End PBXVariantGroup section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | 9C10C40D1BF34592001FE535 /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 203 | CLANG_CXX_LIBRARY = "libc++"; 204 | CLANG_ENABLE_MODULES = YES; 205 | CLANG_ENABLE_OBJC_ARC = YES; 206 | CLANG_WARN_BOOL_CONVERSION = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 216 | COPY_PHASE_STRIP = NO; 217 | DEBUG_INFORMATION_FORMAT = dwarf; 218 | ENABLE_STRICT_OBJC_MSGSEND = YES; 219 | ENABLE_TESTABILITY = YES; 220 | GCC_C_LANGUAGE_STANDARD = gnu99; 221 | GCC_DYNAMIC_NO_PIC = NO; 222 | GCC_NO_COMMON_BLOCKS = YES; 223 | GCC_OPTIMIZATION_LEVEL = 0; 224 | GCC_PREPROCESSOR_DEFINITIONS = ( 225 | "DEBUG=1", 226 | "$(inherited)", 227 | ); 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 235 | MTL_ENABLE_DEBUG_INFO = YES; 236 | ONLY_ACTIVE_ARCH = YES; 237 | SDKROOT = iphoneos; 238 | TARGETED_DEVICE_FAMILY = "1,2"; 239 | }; 240 | name = Debug; 241 | }; 242 | 9C10C40E1BF34592001FE535 /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 247 | CLANG_CXX_LIBRARY = "libc++"; 248 | CLANG_ENABLE_MODULES = YES; 249 | CLANG_ENABLE_OBJC_ARC = YES; 250 | CLANG_WARN_BOOL_CONVERSION = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INT_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_UNREACHABLE_CODE = YES; 258 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 259 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 260 | COPY_PHASE_STRIP = NO; 261 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 262 | ENABLE_NS_ASSERTIONS = NO; 263 | ENABLE_STRICT_OBJC_MSGSEND = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_NO_COMMON_BLOCKS = YES; 266 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 267 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 268 | GCC_WARN_UNDECLARED_SELECTOR = YES; 269 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 270 | GCC_WARN_UNUSED_FUNCTION = YES; 271 | GCC_WARN_UNUSED_VARIABLE = YES; 272 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 273 | MTL_ENABLE_DEBUG_INFO = NO; 274 | SDKROOT = iphoneos; 275 | TARGETED_DEVICE_FAMILY = "1,2"; 276 | VALIDATE_PRODUCT = YES; 277 | }; 278 | name = Release; 279 | }; 280 | 9C10C4101BF34592001FE535 /* Debug */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 284 | INFOPLIST_FILE = SimplePlaying/Info.plist; 285 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 286 | PRODUCT_BUNDLE_IDENTIFIER = SK.SimplePlaying; 287 | PRODUCT_NAME = "$(TARGET_NAME)"; 288 | }; 289 | name = Debug; 290 | }; 291 | 9C10C4111BF34592001FE535 /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 295 | INFOPLIST_FILE = SimplePlaying/Info.plist; 296 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 297 | PRODUCT_BUNDLE_IDENTIFIER = SK.SimplePlaying; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | }; 300 | name = Release; 301 | }; 302 | /* End XCBuildConfiguration section */ 303 | 304 | /* Begin XCConfigurationList section */ 305 | 9C10C3F31BF34592001FE535 /* Build configuration list for PBXProject "SimplePlaying" */ = { 306 | isa = XCConfigurationList; 307 | buildConfigurations = ( 308 | 9C10C40D1BF34592001FE535 /* Debug */, 309 | 9C10C40E1BF34592001FE535 /* Release */, 310 | ); 311 | defaultConfigurationIsVisible = 0; 312 | defaultConfigurationName = Release; 313 | }; 314 | 9C10C40F1BF34592001FE535 /* Build configuration list for PBXNativeTarget "SimplePlaying" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | 9C10C4101BF34592001FE535 /* Debug */, 318 | 9C10C4111BF34592001FE535 /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | }; 322 | /* End XCConfigurationList section */ 323 | }; 324 | rootObject = 9C10C3F01BF34592001FE535 /* Project object */; 325 | } 326 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/Assets.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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 40 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | en 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | APPL 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleSignature 25 | ???? 26 | CFBundleVersion 27 | 1 28 | LSRequiresIPhoneOS 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/SKAudioBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioBuffer.h 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef struct { 13 | AudioStreamPacketDescription packetDescription; 14 | void *data; 15 | } AudioPacketInfo; 16 | 17 | @class SKAudioBuffer; 18 | 19 | @protocol SKAudioBufferDelegate 20 | 21 | - (AudioStreamBasicDescription)usedAudioStreamBasicDescription; 22 | - (void)audioBufferDidBeginReadPacket:(SKAudioBuffer *)inBuffer; 23 | @end 24 | 25 | @interface SKAudioBuffer : NSObject 26 | { 27 | __weak id delegate; 28 | 29 | AudioPacketInfo *packets; 30 | size_t packetWriteIndex; 31 | size_t packetReadIndex; 32 | size_t packetCount; 33 | 34 | NSMutableData *audioData; 35 | NSMutableData *packetDescData; 36 | NSUInteger packetReadHead; 37 | NSUInteger readPacketIndex; 38 | } 39 | 40 | 41 | - (void)storePacketData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount; 42 | - (void)movePacketReadIndex; 43 | 44 | @property (readonly, nonatomic) size_t availablePacketCount; 45 | @property (weak, nonatomic) id delegate; 46 | @property (readonly, nonatomic) AudioPacketInfo currentPacketInfo; 47 | @end 48 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/SKAudioBuffer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioBuffer.m 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import "SKAudioBuffer.h" 10 | 11 | @implementation SKAudioBuffer 12 | 13 | - (id)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | 18 | packetCount = 2048; 19 | packets = (AudioPacketInfo *)calloc(packetCount, sizeof(AudioPacketInfo)); 20 | 21 | audioData = [[NSMutableData alloc] init]; 22 | packetDescData = [[NSMutableData alloc] init]; 23 | } 24 | return self; 25 | } 26 | 27 | 28 | - (void)storePacketData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount 29 | { 30 | // for (NSUInteger packetIndex = 0; packetIndex < inPacketsCount ; packetIndex ++) { 31 | // inPacketDescriptions[packetIndex].mStartOffset += audioData.length; 32 | // } 33 | // 34 | // @synchronized (self) { 35 | // [audioData appendBytes:inBytes length:inLength]; 36 | // [packetDescData appendBytes:inPacketDescriptions length:sizeof(AudioStreamPacketDescription) * inPacketsCount]; 37 | // availablePacketCount += inPacketsCount; 38 | // } 39 | 40 | @synchronized (self) { 41 | 42 | for (size_t index = 0; index < inPacketsCount; index ++) { 43 | 44 | if (packetWriteIndex >= packetCount) { 45 | size_t oldSize = packetCount * sizeof(AudioPacketInfo); 46 | packetCount = packetCount * 2; 47 | packets = (AudioPacketInfo *)realloc(packets, packetCount * sizeof(AudioPacketInfo)); 48 | bzero((void *)packets + oldSize, oldSize); 49 | } 50 | AudioStreamPacketDescription emptyDescription; 51 | 52 | if (!inPacketDescriptions) { 53 | emptyDescription.mStartOffset = index; 54 | emptyDescription.mDataByteSize = 1; 55 | emptyDescription.mVariableFramesInPacket = 0; 56 | } 57 | 58 | AudioStreamPacketDescription *currentDescription = inPacketDescriptions ? &(inPacketDescriptions[index]) : &emptyDescription; 59 | 60 | AudioPacketInfo *nextInfo = &packets[packetWriteIndex]; 61 | if (nextInfo->data) { 62 | free(nextInfo->data); 63 | nextInfo->data = NULL; 64 | } 65 | nextInfo->data = malloc(currentDescription->mDataByteSize); 66 | NSAssert(nextInfo->data, @"Must allocate memory for current packet"); 67 | memcpy(nextInfo->data, inBytes + currentDescription->mStartOffset, currentDescription->mDataByteSize); 68 | memcpy(&nextInfo->packetDescription, currentDescription, sizeof(AudioStreamPacketDescription)); 69 | 70 | packetWriteIndex++; 71 | 72 | _availablePacketCount++; 73 | } 74 | } 75 | } 76 | 77 | - (void)setPacketReadIndex:(size_t)inNewIndex 78 | { 79 | size_t max = _availablePacketCount; 80 | 81 | if (inNewIndex > max) { 82 | packetReadIndex = max; 83 | return; 84 | } 85 | 86 | if (inNewIndex < packetWriteIndex) { 87 | packetReadIndex = inNewIndex; 88 | } 89 | else { 90 | packetReadIndex = packetWriteIndex; 91 | } 92 | } 93 | 94 | - (void)movePacketReadIndex 95 | { 96 | [self setPacketReadIndex:packetReadIndex + 1]; 97 | } 98 | 99 | - (AudioPacketInfo)currentPacketInfo 100 | { 101 | // @synchronized (self) { 102 | // if (readPacketIndex >= availablePacketCount) { 103 | // inCallback(nil, 0, nil, YES); 104 | // return; 105 | // } 106 | // if (readPacketIndex == 0) { 107 | // [delegate audioBufferDidBeginReadPacket:self]; 108 | // } 109 | // 110 | // AudioStreamPacketDescription* packetDescriptions = (AudioStreamPacketDescription* )packetDescData.bytes; 111 | // 112 | // AudioPacketInfo *packet = (AudioPacketInfo *)calloc(1, sizeof(AudioPacketInfo)); 113 | // packet->data = malloc(packetDescriptions[readPacketIndex].mDataByteSize); 114 | // memcpy(packet->data, audioData.bytes + packetDescriptions[readPacketIndex].mStartOffset, packetDescriptions[readPacketIndex].mDataByteSize); 115 | // memcpy(&packet->packetDescription, &packetDescriptions[readPacketIndex], sizeof(AudioStreamPacketDescription)); 116 | // 117 | // readPacketIndex ++; 118 | // 119 | // return *packet; 120 | // } 121 | return packets[packetReadIndex]; 122 | } 123 | 124 | @synthesize delegate; 125 | @synthesize currentPacketInfo; 126 | @end 127 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/SKAudioConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioConverter.h 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SKAudioBuffer.h" 12 | 13 | @interface SKAudioConverter : NSObject 14 | { 15 | AudioStreamBasicDescription audioStreamDescription; 16 | AudioStreamBasicDescription destFormat; 17 | AudioConverterRef converter; 18 | AudioBufferList *renderBufferList; 19 | UInt32 renderBufferSize; 20 | } 21 | 22 | AudioStreamBasicDescription LinearPCMStreamDescription(); 23 | 24 | - (instancetype)initWithSourceFormat:(AudioStreamBasicDescription *)sourceFormat; 25 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber buffer:(SKAudioBuffer *)inBuffer; 26 | 27 | - (void)_fillBufferlist:(AudioBufferList *)ioData withBuffer:(SKAudioBuffer *)buffer packetDescription:(AudioStreamPacketDescription** )outDataPacketDescription; 28 | @property (readonly, nonatomic) double packetsPerSecond; 29 | @end 30 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/SKAudioConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioConverter.m 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "SKAudioConverter.h" 10 | 11 | static OSStatus AudioConverterFiller(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData); 12 | 13 | OSStatus AudioConverterFiller (AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) 14 | { 15 | NSArray *args = (__bridge NSArray *)inUserData; 16 | SKAudioConverter *self = args[0]; 17 | SKAudioBuffer *buffer = args[1]; 18 | // *ioNumberDataPackets = 1; 19 | [self _fillBufferlist:ioData withBuffer:buffer packetDescription:outDataPacketDescription]; 20 | return noErr; 21 | } 22 | 23 | AudioStreamBasicDescription LinearPCMStreamDescription() 24 | { 25 | AudioStreamBasicDescription destFormat; 26 | bzero(&destFormat, sizeof(AudioStreamBasicDescription)); 27 | destFormat.mSampleRate = 44100.0; 28 | destFormat.mFormatID = kAudioFormatLinearPCM; 29 | destFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; 30 | 31 | destFormat.mFramesPerPacket = 1; 32 | destFormat.mBytesPerPacket = 4; 33 | destFormat.mBytesPerFrame = 4; 34 | destFormat.mChannelsPerFrame = 2; 35 | destFormat.mBitsPerChannel = 16; 36 | destFormat.mReserved = 0; 37 | return destFormat; 38 | } 39 | 40 | @implementation SKAudioConverter 41 | 42 | - (instancetype)initWithSourceFormat:(AudioStreamBasicDescription *)sourceFormat 43 | { 44 | self = [super init]; 45 | if (self) { 46 | audioStreamDescription = *sourceFormat; 47 | destFormat = LinearPCMStreamDescription(); 48 | AudioConverterNew(&audioStreamDescription, &destFormat, &converter); 49 | 50 | UInt32 packetSize = 44100 * 4; 51 | renderBufferSize = packetSize; 52 | renderBufferList = (AudioBufferList *)calloc(1, sizeof(UInt32) + sizeof(AudioBuffer)); 53 | renderBufferList->mNumberBuffers = 1; 54 | renderBufferList->mBuffers[0].mNumberChannels = 2; 55 | renderBufferList->mBuffers[0].mDataByteSize = packetSize; 56 | renderBufferList->mBuffers[0].mData = calloc(1, packetSize); 57 | } 58 | return self; 59 | } 60 | 61 | - (void)_fillBufferlist:(AudioBufferList *)ioData withBuffer:(SKAudioBuffer *)buffer packetDescription:(AudioStreamPacketDescription** )outDataPacketDescription 62 | { 63 | static AudioStreamPacketDescription aspdesc; 64 | 65 | AudioPacketInfo currentPacketInfo = buffer.currentPacketInfo; 66 | 67 | void *data = currentPacketInfo.data; 68 | UInt32 length = (UInt32)currentPacketInfo.packetDescription.mDataByteSize; 69 | ioData->mBuffers[0].mData = data; 70 | ioData->mBuffers[0].mDataByteSize = length; 71 | ioData->mNumberBuffers = 1; 72 | 73 | *outDataPacketDescription = &aspdesc; 74 | aspdesc.mDataByteSize = length; 75 | aspdesc.mStartOffset = 0; 76 | aspdesc.mVariableFramesInPacket = 1; 77 | 78 | [buffer movePacketReadIndex]; 79 | } 80 | 81 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber buffer:(SKAudioBuffer *)inBuffer 82 | { 83 | UInt32 packetSize = inNumberOfFrames; 84 | NSArray *args = @[self, inBuffer]; 85 | OSStatus status = noErr; 86 | 87 | status = AudioConverterFillComplexBuffer(converter, AudioConverterFiller, (__bridge void *)(args), &packetSize, renderBufferList, NULL); 88 | 89 | if (noErr == status && packetSize) { 90 | inIoData->mNumberBuffers = 1; 91 | inIoData->mBuffers[0].mNumberChannels = 2; 92 | inIoData->mBuffers[0].mDataByteSize = renderBufferList->mBuffers[0].mDataByteSize; 93 | inIoData->mBuffers[0].mData = renderBufferList->mBuffers[0].mData; 94 | status = noErr; 95 | } 96 | return status; 97 | } 98 | 99 | - (double)packetsPerSecond 100 | { 101 | if (!(audioStreamDescription.mFramesPerPacket > 0)) { 102 | return 0; 103 | } 104 | return audioStreamDescription.mSampleRate / audioStreamDescription.mFramesPerPacket; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/SKAudioParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioParser.h 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class SKAudioParser; 13 | 14 | @protocol SKAudioParserDelegate 15 | 16 | - (void)audioStreamParser:(SKAudioParser *)inParser didObtainStreamDescription:(AudioStreamBasicDescription *)inDescription; 17 | - (void)audioStreamParser:(SKAudioParser *)inParser packetData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount; 18 | 19 | @end 20 | 21 | @interface SKAudioParser : NSObject 22 | { 23 | AudioFileStreamID audioFileStreamID; 24 | __weak id delegate; 25 | } 26 | 27 | - (void)parseData:(NSData *)inData; 28 | 29 | @property (weak, nonatomic) id delegate; 30 | @end 31 | 32 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/SKAudioParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKAudioParser.m 3 | // SKAudioQueue 4 | // 5 | // Created by steven on 2015/1/22. 6 | // Copyright (c) 2015年 KKBOX. All rights reserved. 7 | // 8 | 9 | #import "SKAudioParser.h" 10 | 11 | @implementation SKAudioParser 12 | 13 | 14 | void audioFileStreamPropertyListenerProc(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags) 15 | { 16 | /* 17 | kAudioFileStreamProperty_ReadyToProducePackets = 'redy', 18 | kAudioFileStreamProperty_FileFormat = 'ffmt', 19 | kAudioFileStreamProperty_DataFormat = 'dfmt', 20 | kAudioFileStreamProperty_FormatList = 'flst', 21 | kAudioFileStreamProperty_MagicCookieData = 'mgic', 22 | kAudioFileStreamProperty_AudioDataByteCount = 'bcnt', 23 | kAudioFileStreamProperty_AudioDataPacketCount = 'pcnt', 24 | kAudioFileStreamProperty_MaximumPacketSize = 'psze', 25 | kAudioFileStreamProperty_DataOffset = 'doff', 26 | kAudioFileStreamProperty_ChannelLayout = 'cmap', 27 | kAudioFileStreamProperty_PacketToFrame = 'pkfr', 28 | kAudioFileStreamProperty_FrameToPacket = 'frpk', 29 | kAudioFileStreamProperty_PacketToByte = 'pkby', 30 | kAudioFileStreamProperty_ByteToPacket = 'bypk', 31 | kAudioFileStreamProperty_PacketTableInfo = 'pnfo', 32 | kAudioFileStreamProperty_PacketSizeUpperBound = 'pkub', 33 | kAudioFileStreamProperty_AverageBytesPerPacket = 'abpp', 34 | kAudioFileStreamProperty_BitRate = 'brat', 35 | kAudioFileStreamProperty_InfoDictionary = 'info' 36 | */ 37 | if (inPropertyID == 'dfmt') { 38 | AudioStreamBasicDescription description; 39 | UInt32 descriptionSize = sizeof(description); 40 | AudioFileStreamGetProperty(inAudioFileStream, inPropertyID, &descriptionSize, &description); 41 | [((__bridge SKAudioParser *)inClientData).delegate audioStreamParser:(__bridge SKAudioParser *)inClientData didObtainStreamDescription:&description]; 42 | } 43 | } 44 | 45 | 46 | void audioFileStreamPacketsProc(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions) 47 | { 48 | [((__bridge SKAudioParser *)inClientData).delegate audioStreamParser:((__bridge SKAudioParser *)inClientData) packetData:inInputData dataLength:inNumberBytes packetDescriptions:inPacketDescriptions packetsCount:inNumberPackets]; 49 | 50 | } 51 | 52 | - (id)init 53 | { 54 | self = [super init]; 55 | if (self) { 56 | 57 | AudioFileStreamOpen((__bridge void *)(self), audioFileStreamPropertyListenerProc, audioFileStreamPacketsProc, kAudioFileMP3Type, &audioFileStreamID); 58 | 59 | } 60 | return self; 61 | } 62 | 63 | - (void)parseData:(NSData *)inData 64 | { 65 | AudioFileStreamParseBytes(audioFileStreamID, (UInt32)[inData length], [inData bytes], 0); 66 | } 67 | 68 | @synthesize delegate; 69 | @end 70 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import 12 | #import "SKAudioParser.h" 13 | #import "SKAudioBuffer.h" 14 | #import "SKAudioConverter.h" 15 | 16 | @interface ViewController () 17 | { 18 | AUGraph audioGraph; 19 | AUNode node; 20 | AudioUnit audioUnit; 21 | 22 | SKAudioParser *parser; 23 | SKAudioBuffer *buffer; 24 | 25 | SKAudioConverter *converter; 26 | IBOutlet UITextField *textFeild; 27 | IBOutlet UILabel *tip; 28 | } 29 | @end 30 | 31 | static void MyAudioUnitPropertyListenerProc(void *inRefCon, AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope,AudioUnitElement inElement); 32 | 33 | static OSStatus RenderCallback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); 34 | 35 | @implementation ViewController 36 | 37 | - (id)initWithCoder:(NSCoder *)aDecoder 38 | { 39 | self = [super initWithCoder:aDecoder]; 40 | if (self) { 41 | 42 | parser = [[SKAudioParser alloc] init]; 43 | parser.delegate = self; 44 | 45 | buffer = [[SKAudioBuffer alloc] init]; 46 | 47 | OSStatus status = noErr; 48 | status = NewAUGraph(&audioGraph); 49 | status = AUGraphOpen(audioGraph); 50 | 51 | AudioComponentDescription unitDescription = [self unitDescription]; 52 | status = AUGraphAddNode(audioGraph, &unitDescription, &node); 53 | status = AUGraphNodeInfo(audioGraph, node, &unitDescription, &audioUnit); 54 | UInt32 maxFPS = 4096; 55 | status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0,&maxFPS, sizeof(maxFPS)); 56 | 57 | AudioStreamBasicDescription destFormat = LinearPCMStreamDescription(); 58 | 59 | status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &destFormat, sizeof(destFormat)); 60 | 61 | status = AudioUnitAddPropertyListener(audioUnit, kAudioOutputUnitProperty_IsRunning, MyAudioUnitPropertyListenerProc, (__bridge void *)(self)); 62 | 63 | AURenderCallbackStruct callbackStruct; 64 | callbackStruct.inputProcRefCon = (__bridge void *)(self); 65 | callbackStruct.inputProc = RenderCallback; 66 | 67 | status = AUGraphSetNodeInputCallback(audioGraph, node, 0, &callbackStruct); 68 | status = AUGraphInitialize(audioGraph); 69 | AudioOutputUnitStop(audioUnit); 70 | 71 | } 72 | return self; 73 | } 74 | 75 | - (AudioComponentDescription)unitDescription 76 | { 77 | AudioComponentDescription outputUnitDescription; 78 | bzero(&outputUnitDescription, sizeof(AudioComponentDescription)); 79 | outputUnitDescription.componentType = kAudioUnitType_Output; 80 | outputUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO; 81 | outputUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 82 | outputUnitDescription.componentFlags = 0; 83 | outputUnitDescription.componentFlagsMask = 0; 84 | return outputUnitDescription; 85 | } 86 | 87 | - (void)viewDidLoad { 88 | [super viewDidLoad]; 89 | OSStatus aError = AUGraphStart(audioGraph); 90 | aError = AudioOutputUnitStart(audioUnit); 91 | } 92 | 93 | - (void)textFieldDidEndEditing:(UITextField *)textField { 94 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 95 | NSURLSessionConfiguration *myConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; 96 | NSURLSession *operationSession = [NSURLSession sessionWithConfiguration:myConfiguration delegate:(id)self delegateQueue:operationQueue]; 97 | 98 | NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:textFeild.text]]; 99 | NSURLSessionDataTask *task = [operationSession dataTaskWithRequest:request]; 100 | [task resume]; 101 | } 102 | 103 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 104 | [textFeild resignFirstResponder]; 105 | [textFeild setEnabled:NO]; 106 | return YES; 107 | } 108 | 109 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler 110 | { 111 | dispatch_async(dispatch_get_main_queue(), ^{ 112 | tip.text = @"receiving data..."; 113 | tip.textColor = UIColor.blackColor; 114 | }); 115 | completionHandler(NSURLSessionResponseAllow); 116 | } 117 | 118 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data 119 | { 120 | [parser parseData:data]; 121 | } 122 | 123 | - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 124 | { 125 | dispatch_async(dispatch_get_main_queue(), ^{ 126 | if (error) { 127 | tip.textColor = UIColor.redColor; 128 | tip.text = @"Fail"; 129 | textFeild.text = @""; 130 | [textFeild setEnabled:YES]; 131 | return; 132 | } 133 | tip.text = @""; 134 | }); 135 | } 136 | 137 | - (void)audioStreamParser:(SKAudioParser *)inParser didObtainStreamDescription:(AudioStreamBasicDescription *)inDescription 138 | { 139 | NSLog(@"mSampleRate: %f", inDescription->mSampleRate); 140 | NSLog(@"mFormatID: %u", (unsigned int)inDescription->mFormatID); 141 | NSLog(@"mFormatFlags: %u", (unsigned int)inDescription->mFormatFlags); 142 | NSLog(@"mBytesPerPacket: %u", (unsigned int)inDescription->mBytesPerPacket); 143 | NSLog(@"mFramesPerPacket: %u", (unsigned int)inDescription->mFramesPerPacket); 144 | NSLog(@"mBytesPerFrame: %u", (unsigned int)inDescription->mBytesPerFrame); 145 | NSLog(@"mChannelsPerFrame: %u", (unsigned int)inDescription->mChannelsPerFrame); 146 | NSLog(@"mBitsPerChannel: %u", (unsigned int)inDescription->mBitsPerChannel); 147 | NSLog(@"mReserved: %u", (unsigned int)inDescription->mReserved); 148 | 149 | converter = [[SKAudioConverter alloc] initWithSourceFormat:inDescription]; 150 | 151 | } 152 | - (void)audioStreamParser:(SKAudioParser *)inParser packetData:(const void * )inBytes dataLength:(UInt32)inLength packetDescriptions:(AudioStreamPacketDescription* )inPacketDescriptions packetsCount:(UInt32)inPacketsCount 153 | { 154 | [buffer storePacketData:inBytes dataLength:inLength packetDescriptions:inPacketDescriptions packetsCount:inPacketsCount]; 155 | } 156 | 157 | - (OSStatus)requestNumberOfFrames:(UInt32)inNumberOfFrames ioData:(AudioBufferList *)inIoData busNumber:(UInt32)inBusNumber 158 | { 159 | if (buffer.availablePacketCount < converter.packetsPerSecond * 4) { 160 | return -1; 161 | } 162 | OSStatus status = [converter requestNumberOfFrames:inNumberOfFrames ioData:inIoData busNumber:inBusNumber buffer:buffer]; 163 | /* remove vocal 164 | UInt16 *data = inIoData->mBuffers[0].mData; 165 | for (int i = 0; i < inIoData->mBuffers[0].mDataByteSize; i += 2) { 166 | UInt16 left = data[i]; 167 | UInt16 right = data[i + 1]; 168 | UInt16 new = left - right; 169 | data[i] = new; 170 | data[i+1] = new; 171 | 172 | } 173 | */ 174 | return status; 175 | } 176 | 177 | void MyAudioUnitPropertyListenerProc(void *inRefCon, AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope,AudioUnitElement inElement) 178 | { 179 | 180 | } 181 | 182 | static OSStatus RenderCallback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 183 | { 184 | ViewController *self = (__bridge ViewController *)userData; 185 | 186 | OSStatus status = [self requestNumberOfFrames:inNumberFrames ioData:ioData busNumber:inBusNumber]; 187 | 188 | return status; 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /AudioUnitSample/SimplePlaying/SimplePlaying/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SimplePlaying 4 | // 5 | // Created by StevenKuo on 2015/11/11. 6 | // Copyright © 2015年 StevenKuo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AudioUnitSample 2 | 3 | ## SimplePlaying 4 | Uses remoteIO audioUnit to play streaming audio. 5 | 6 | ## RemoteIO 7 | Connects remoteIO unit and mix unit to fetch voice by microphone and playing streaming audio. 8 | 9 | ## MixPlaying 10 | Connects remoteIO unit and mix unit to play streaming audio from two resources. 11 | --------------------------------------------------------------------------------