├── MCAudioFileStream.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── MCAudioFileStream ├── AppDelegate.h ├── AppDelegate.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── MCAudioFileStream-Info.plist ├── MCAudioFileStream-Prefix.pch ├── MCAudioFileStream.h ├── MCAudioFileStream.m ├── MCParsedAudioData.h ├── MCParsedAudioData.m ├── MP3Sample.mp3 ├── en.lproj │ └── InfoPlist.strings └── main.m ├── MCAudioFileStreamTests ├── MCAudioFileStreamTests-Info.plist ├── MCAudioFileStreamTests.m └── en.lproj │ └── InfoPlist.strings └── README.md /MCAudioFileStream.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DEBF4F521970FFB90055090F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F511970FFB90055090F /* Foundation.framework */; }; 11 | DEBF4F541970FFB90055090F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F531970FFB90055090F /* CoreGraphics.framework */; }; 12 | DEBF4F561970FFB90055090F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F551970FFB90055090F /* UIKit.framework */; }; 13 | DEBF4F5C1970FFB90055090F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DEBF4F5A1970FFB90055090F /* InfoPlist.strings */; }; 14 | DEBF4F5E1970FFB90055090F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBF4F5D1970FFB90055090F /* main.m */; }; 15 | DEBF4F621970FFB90055090F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBF4F611970FFB90055090F /* AppDelegate.m */; }; 16 | DEBF4F641970FFB90055090F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DEBF4F631970FFB90055090F /* Images.xcassets */; }; 17 | DEBF4F6B1970FFB90055090F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F6A1970FFB90055090F /* XCTest.framework */; }; 18 | DEBF4F6C1970FFB90055090F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F511970FFB90055090F /* Foundation.framework */; }; 19 | DEBF4F6D1970FFB90055090F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F551970FFB90055090F /* UIKit.framework */; }; 20 | DEBF4F751970FFB90055090F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DEBF4F731970FFB90055090F /* InfoPlist.strings */; }; 21 | DEBF4F771970FFB90055090F /* MCAudioFileStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBF4F761970FFB90055090F /* MCAudioFileStreamTests.m */; }; 22 | DEBF4F821970FFD70055090F /* MCAudioFileStream.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBF4F811970FFD70055090F /* MCAudioFileStream.m */; }; 23 | DEBF4F85197106070055090F /* MCParsedAudioData.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBF4F84197106070055090F /* MCParsedAudioData.m */; }; 24 | DEBF4F8A1971114B0055090F /* MP3Sample.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = DEBF4F891971114B0055090F /* MP3Sample.mp3 */; }; 25 | DEBF4F8C197115070055090F /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F8B197115070055090F /* CoreAudio.framework */; }; 26 | DEBF4F8E1971150C0055090F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBF4F8D1971150C0055090F /* AudioToolbox.framework */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | DEBF4F6E1970FFB90055090F /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = DEBF4F461970FFB90055090F /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = DEBF4F4D1970FFB90055090F; 35 | remoteInfo = MCAudioFileStream; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | DEBF4F4E1970FFB90055090F /* MCAudioFileStream.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MCAudioFileStream.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | DEBF4F511970FFB90055090F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 42 | DEBF4F531970FFB90055090F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 43 | DEBF4F551970FFB90055090F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 44 | DEBF4F591970FFB90055090F /* MCAudioFileStream-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MCAudioFileStream-Info.plist"; sourceTree = ""; }; 45 | DEBF4F5B1970FFB90055090F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 46 | DEBF4F5D1970FFB90055090F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 47 | DEBF4F5F1970FFB90055090F /* MCAudioFileStream-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MCAudioFileStream-Prefix.pch"; sourceTree = ""; }; 48 | DEBF4F601970FFB90055090F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | DEBF4F611970FFB90055090F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | DEBF4F631970FFB90055090F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 51 | DEBF4F691970FFB90055090F /* MCAudioFileStreamTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MCAudioFileStreamTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | DEBF4F6A1970FFB90055090F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 53 | DEBF4F721970FFB90055090F /* MCAudioFileStreamTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MCAudioFileStreamTests-Info.plist"; sourceTree = ""; }; 54 | DEBF4F741970FFB90055090F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 55 | DEBF4F761970FFB90055090F /* MCAudioFileStreamTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCAudioFileStreamTests.m; sourceTree = ""; }; 56 | DEBF4F801970FFD70055090F /* MCAudioFileStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAudioFileStream.h; sourceTree = ""; }; 57 | DEBF4F811970FFD70055090F /* MCAudioFileStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCAudioFileStream.m; sourceTree = ""; }; 58 | DEBF4F83197106070055090F /* MCParsedAudioData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCParsedAudioData.h; sourceTree = ""; }; 59 | DEBF4F84197106070055090F /* MCParsedAudioData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCParsedAudioData.m; sourceTree = ""; }; 60 | DEBF4F891971114B0055090F /* MP3Sample.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = MP3Sample.mp3; sourceTree = ""; }; 61 | DEBF4F8B197115070055090F /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; 62 | DEBF4F8D1971150C0055090F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | DEBF4F4B1970FFB90055090F /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | DEBF4F8E1971150C0055090F /* AudioToolbox.framework in Frameworks */, 71 | DEBF4F8C197115070055090F /* CoreAudio.framework in Frameworks */, 72 | DEBF4F541970FFB90055090F /* CoreGraphics.framework in Frameworks */, 73 | DEBF4F561970FFB90055090F /* UIKit.framework in Frameworks */, 74 | DEBF4F521970FFB90055090F /* Foundation.framework in Frameworks */, 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | DEBF4F661970FFB90055090F /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | DEBF4F6B1970FFB90055090F /* XCTest.framework in Frameworks */, 83 | DEBF4F6D1970FFB90055090F /* UIKit.framework in Frameworks */, 84 | DEBF4F6C1970FFB90055090F /* Foundation.framework in Frameworks */, 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | DEBF4F451970FFB90055090F = { 92 | isa = PBXGroup; 93 | children = ( 94 | DEBF4F571970FFB90055090F /* MCAudioFileStream */, 95 | DEBF4F701970FFB90055090F /* MCAudioFileStreamTests */, 96 | DEBF4F501970FFB90055090F /* Frameworks */, 97 | DEBF4F4F1970FFB90055090F /* Products */, 98 | ); 99 | sourceTree = ""; 100 | }; 101 | DEBF4F4F1970FFB90055090F /* Products */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | DEBF4F4E1970FFB90055090F /* MCAudioFileStream.app */, 105 | DEBF4F691970FFB90055090F /* MCAudioFileStreamTests.xctest */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | DEBF4F501970FFB90055090F /* Frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | DEBF4F8D1971150C0055090F /* AudioToolbox.framework */, 114 | DEBF4F8B197115070055090F /* CoreAudio.framework */, 115 | DEBF4F511970FFB90055090F /* Foundation.framework */, 116 | DEBF4F531970FFB90055090F /* CoreGraphics.framework */, 117 | DEBF4F551970FFB90055090F /* UIKit.framework */, 118 | DEBF4F6A1970FFB90055090F /* XCTest.framework */, 119 | ); 120 | name = Frameworks; 121 | sourceTree = ""; 122 | }; 123 | DEBF4F571970FFB90055090F /* MCAudioFileStream */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | DEBF4F83197106070055090F /* MCParsedAudioData.h */, 127 | DEBF4F84197106070055090F /* MCParsedAudioData.m */, 128 | DEBF4F801970FFD70055090F /* MCAudioFileStream.h */, 129 | DEBF4F811970FFD70055090F /* MCAudioFileStream.m */, 130 | DEBF4F601970FFB90055090F /* AppDelegate.h */, 131 | DEBF4F611970FFB90055090F /* AppDelegate.m */, 132 | DEBF4F631970FFB90055090F /* Images.xcassets */, 133 | DEBF4F581970FFB90055090F /* Supporting Files */, 134 | ); 135 | path = MCAudioFileStream; 136 | sourceTree = ""; 137 | }; 138 | DEBF4F581970FFB90055090F /* Supporting Files */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | DEBF4F891971114B0055090F /* MP3Sample.mp3 */, 142 | DEBF4F591970FFB90055090F /* MCAudioFileStream-Info.plist */, 143 | DEBF4F5A1970FFB90055090F /* InfoPlist.strings */, 144 | DEBF4F5D1970FFB90055090F /* main.m */, 145 | DEBF4F5F1970FFB90055090F /* MCAudioFileStream-Prefix.pch */, 146 | ); 147 | name = "Supporting Files"; 148 | sourceTree = ""; 149 | }; 150 | DEBF4F701970FFB90055090F /* MCAudioFileStreamTests */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | DEBF4F761970FFB90055090F /* MCAudioFileStreamTests.m */, 154 | DEBF4F711970FFB90055090F /* Supporting Files */, 155 | ); 156 | path = MCAudioFileStreamTests; 157 | sourceTree = ""; 158 | }; 159 | DEBF4F711970FFB90055090F /* Supporting Files */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | DEBF4F721970FFB90055090F /* MCAudioFileStreamTests-Info.plist */, 163 | DEBF4F731970FFB90055090F /* InfoPlist.strings */, 164 | ); 165 | name = "Supporting Files"; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | DEBF4F4D1970FFB90055090F /* MCAudioFileStream */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = DEBF4F7A1970FFB90055090F /* Build configuration list for PBXNativeTarget "MCAudioFileStream" */; 174 | buildPhases = ( 175 | DEBF4F4A1970FFB90055090F /* Sources */, 176 | DEBF4F4B1970FFB90055090F /* Frameworks */, 177 | DEBF4F4C1970FFB90055090F /* Resources */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | ); 183 | name = MCAudioFileStream; 184 | productName = MCAudioFileStream; 185 | productReference = DEBF4F4E1970FFB90055090F /* MCAudioFileStream.app */; 186 | productType = "com.apple.product-type.application"; 187 | }; 188 | DEBF4F681970FFB90055090F /* MCAudioFileStreamTests */ = { 189 | isa = PBXNativeTarget; 190 | buildConfigurationList = DEBF4F7D1970FFB90055090F /* Build configuration list for PBXNativeTarget "MCAudioFileStreamTests" */; 191 | buildPhases = ( 192 | DEBF4F651970FFB90055090F /* Sources */, 193 | DEBF4F661970FFB90055090F /* Frameworks */, 194 | DEBF4F671970FFB90055090F /* Resources */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | DEBF4F6F1970FFB90055090F /* PBXTargetDependency */, 200 | ); 201 | name = MCAudioFileStreamTests; 202 | productName = MCAudioFileStreamTests; 203 | productReference = DEBF4F691970FFB90055090F /* MCAudioFileStreamTests.xctest */; 204 | productType = "com.apple.product-type.bundle.unit-test"; 205 | }; 206 | /* End PBXNativeTarget section */ 207 | 208 | /* Begin PBXProject section */ 209 | DEBF4F461970FFB90055090F /* Project object */ = { 210 | isa = PBXProject; 211 | attributes = { 212 | LastUpgradeCheck = 0510; 213 | ORGANIZATIONNAME = Chengyin; 214 | TargetAttributes = { 215 | DEBF4F681970FFB90055090F = { 216 | TestTargetID = DEBF4F4D1970FFB90055090F; 217 | }; 218 | }; 219 | }; 220 | buildConfigurationList = DEBF4F491970FFB90055090F /* Build configuration list for PBXProject "MCAudioFileStream" */; 221 | compatibilityVersion = "Xcode 3.2"; 222 | developmentRegion = English; 223 | hasScannedForEncodings = 0; 224 | knownRegions = ( 225 | en, 226 | ); 227 | mainGroup = DEBF4F451970FFB90055090F; 228 | productRefGroup = DEBF4F4F1970FFB90055090F /* Products */; 229 | projectDirPath = ""; 230 | projectRoot = ""; 231 | targets = ( 232 | DEBF4F4D1970FFB90055090F /* MCAudioFileStream */, 233 | DEBF4F681970FFB90055090F /* MCAudioFileStreamTests */, 234 | ); 235 | }; 236 | /* End PBXProject section */ 237 | 238 | /* Begin PBXResourcesBuildPhase section */ 239 | DEBF4F4C1970FFB90055090F /* Resources */ = { 240 | isa = PBXResourcesBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | DEBF4F5C1970FFB90055090F /* InfoPlist.strings in Resources */, 244 | DEBF4F641970FFB90055090F /* Images.xcassets in Resources */, 245 | DEBF4F8A1971114B0055090F /* MP3Sample.mp3 in Resources */, 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | }; 249 | DEBF4F671970FFB90055090F /* Resources */ = { 250 | isa = PBXResourcesBuildPhase; 251 | buildActionMask = 2147483647; 252 | files = ( 253 | DEBF4F751970FFB90055090F /* InfoPlist.strings in Resources */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | DEBF4F4A1970FFB90055090F /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | DEBF4F621970FFB90055090F /* AppDelegate.m in Sources */, 265 | DEBF4F85197106070055090F /* MCParsedAudioData.m in Sources */, 266 | DEBF4F821970FFD70055090F /* MCAudioFileStream.m in Sources */, 267 | DEBF4F5E1970FFB90055090F /* main.m in Sources */, 268 | ); 269 | runOnlyForDeploymentPostprocessing = 0; 270 | }; 271 | DEBF4F651970FFB90055090F /* Sources */ = { 272 | isa = PBXSourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | DEBF4F771970FFB90055090F /* MCAudioFileStreamTests.m in Sources */, 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | /* End PBXSourcesBuildPhase section */ 280 | 281 | /* Begin PBXTargetDependency section */ 282 | DEBF4F6F1970FFB90055090F /* PBXTargetDependency */ = { 283 | isa = PBXTargetDependency; 284 | target = DEBF4F4D1970FFB90055090F /* MCAudioFileStream */; 285 | targetProxy = DEBF4F6E1970FFB90055090F /* PBXContainerItemProxy */; 286 | }; 287 | /* End PBXTargetDependency section */ 288 | 289 | /* Begin PBXVariantGroup section */ 290 | DEBF4F5A1970FFB90055090F /* InfoPlist.strings */ = { 291 | isa = PBXVariantGroup; 292 | children = ( 293 | DEBF4F5B1970FFB90055090F /* en */, 294 | ); 295 | name = InfoPlist.strings; 296 | sourceTree = ""; 297 | }; 298 | DEBF4F731970FFB90055090F /* InfoPlist.strings */ = { 299 | isa = PBXVariantGroup; 300 | children = ( 301 | DEBF4F741970FFB90055090F /* en */, 302 | ); 303 | name = InfoPlist.strings; 304 | sourceTree = ""; 305 | }; 306 | /* End PBXVariantGroup section */ 307 | 308 | /* Begin XCBuildConfiguration section */ 309 | DEBF4F781970FFB90055090F /* Debug */ = { 310 | isa = XCBuildConfiguration; 311 | buildSettings = { 312 | ALWAYS_SEARCH_USER_PATHS = NO; 313 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 314 | CLANG_CXX_LIBRARY = "libc++"; 315 | CLANG_ENABLE_MODULES = YES; 316 | CLANG_ENABLE_OBJC_ARC = YES; 317 | CLANG_WARN_BOOL_CONVERSION = YES; 318 | CLANG_WARN_CONSTANT_CONVERSION = YES; 319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 320 | CLANG_WARN_EMPTY_BODY = YES; 321 | CLANG_WARN_ENUM_CONVERSION = YES; 322 | CLANG_WARN_INT_CONVERSION = YES; 323 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 324 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 325 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 326 | COPY_PHASE_STRIP = NO; 327 | GCC_C_LANGUAGE_STANDARD = gnu99; 328 | GCC_DYNAMIC_NO_PIC = NO; 329 | GCC_OPTIMIZATION_LEVEL = 0; 330 | GCC_PREPROCESSOR_DEFINITIONS = ( 331 | "DEBUG=1", 332 | "$(inherited)", 333 | ); 334 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 335 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 336 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 337 | GCC_WARN_UNDECLARED_SELECTOR = YES; 338 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 339 | GCC_WARN_UNUSED_FUNCTION = YES; 340 | GCC_WARN_UNUSED_VARIABLE = YES; 341 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 342 | ONLY_ACTIVE_ARCH = YES; 343 | SDKROOT = iphoneos; 344 | }; 345 | name = Debug; 346 | }; 347 | DEBF4F791970FFB90055090F /* Release */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | ALWAYS_SEARCH_USER_PATHS = NO; 351 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 352 | CLANG_CXX_LIBRARY = "libc++"; 353 | CLANG_ENABLE_MODULES = YES; 354 | CLANG_ENABLE_OBJC_ARC = YES; 355 | CLANG_WARN_BOOL_CONVERSION = YES; 356 | CLANG_WARN_CONSTANT_CONVERSION = YES; 357 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 358 | CLANG_WARN_EMPTY_BODY = YES; 359 | CLANG_WARN_ENUM_CONVERSION = YES; 360 | CLANG_WARN_INT_CONVERSION = YES; 361 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 363 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 364 | COPY_PHASE_STRIP = YES; 365 | ENABLE_NS_ASSERTIONS = NO; 366 | GCC_C_LANGUAGE_STANDARD = gnu99; 367 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 368 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 369 | GCC_WARN_UNDECLARED_SELECTOR = YES; 370 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 371 | GCC_WARN_UNUSED_FUNCTION = YES; 372 | GCC_WARN_UNUSED_VARIABLE = YES; 373 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 374 | SDKROOT = iphoneos; 375 | VALIDATE_PRODUCT = YES; 376 | }; 377 | name = Release; 378 | }; 379 | DEBF4F7B1970FFB90055090F /* Debug */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 383 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 384 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 385 | GCC_PREFIX_HEADER = "MCAudioFileStream/MCAudioFileStream-Prefix.pch"; 386 | INFOPLIST_FILE = "MCAudioFileStream/MCAudioFileStream-Info.plist"; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | WRAPPER_EXTENSION = app; 389 | }; 390 | name = Debug; 391 | }; 392 | DEBF4F7C1970FFB90055090F /* Release */ = { 393 | isa = XCBuildConfiguration; 394 | buildSettings = { 395 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 396 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 397 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 398 | GCC_PREFIX_HEADER = "MCAudioFileStream/MCAudioFileStream-Prefix.pch"; 399 | INFOPLIST_FILE = "MCAudioFileStream/MCAudioFileStream-Info.plist"; 400 | PRODUCT_NAME = "$(TARGET_NAME)"; 401 | WRAPPER_EXTENSION = app; 402 | }; 403 | name = Release; 404 | }; 405 | DEBF4F7E1970FFB90055090F /* Debug */ = { 406 | isa = XCBuildConfiguration; 407 | buildSettings = { 408 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/MCAudioFileStream.app/MCAudioFileStream"; 409 | FRAMEWORK_SEARCH_PATHS = ( 410 | "$(SDKROOT)/Developer/Library/Frameworks", 411 | "$(inherited)", 412 | "$(DEVELOPER_FRAMEWORKS_DIR)", 413 | ); 414 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 415 | GCC_PREFIX_HEADER = "MCAudioFileStream/MCAudioFileStream-Prefix.pch"; 416 | GCC_PREPROCESSOR_DEFINITIONS = ( 417 | "DEBUG=1", 418 | "$(inherited)", 419 | ); 420 | INFOPLIST_FILE = "MCAudioFileStreamTests/MCAudioFileStreamTests-Info.plist"; 421 | PRODUCT_NAME = "$(TARGET_NAME)"; 422 | TEST_HOST = "$(BUNDLE_LOADER)"; 423 | WRAPPER_EXTENSION = xctest; 424 | }; 425 | name = Debug; 426 | }; 427 | DEBF4F7F1970FFB90055090F /* Release */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/MCAudioFileStream.app/MCAudioFileStream"; 431 | FRAMEWORK_SEARCH_PATHS = ( 432 | "$(SDKROOT)/Developer/Library/Frameworks", 433 | "$(inherited)", 434 | "$(DEVELOPER_FRAMEWORKS_DIR)", 435 | ); 436 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 437 | GCC_PREFIX_HEADER = "MCAudioFileStream/MCAudioFileStream-Prefix.pch"; 438 | INFOPLIST_FILE = "MCAudioFileStreamTests/MCAudioFileStreamTests-Info.plist"; 439 | PRODUCT_NAME = "$(TARGET_NAME)"; 440 | TEST_HOST = "$(BUNDLE_LOADER)"; 441 | WRAPPER_EXTENSION = xctest; 442 | }; 443 | name = Release; 444 | }; 445 | /* End XCBuildConfiguration section */ 446 | 447 | /* Begin XCConfigurationList section */ 448 | DEBF4F491970FFB90055090F /* Build configuration list for PBXProject "MCAudioFileStream" */ = { 449 | isa = XCConfigurationList; 450 | buildConfigurations = ( 451 | DEBF4F781970FFB90055090F /* Debug */, 452 | DEBF4F791970FFB90055090F /* Release */, 453 | ); 454 | defaultConfigurationIsVisible = 0; 455 | defaultConfigurationName = Release; 456 | }; 457 | DEBF4F7A1970FFB90055090F /* Build configuration list for PBXNativeTarget "MCAudioFileStream" */ = { 458 | isa = XCConfigurationList; 459 | buildConfigurations = ( 460 | DEBF4F7B1970FFB90055090F /* Debug */, 461 | DEBF4F7C1970FFB90055090F /* Release */, 462 | ); 463 | defaultConfigurationIsVisible = 0; 464 | }; 465 | DEBF4F7D1970FFB90055090F /* Build configuration list for PBXNativeTarget "MCAudioFileStreamTests" */ = { 466 | isa = XCConfigurationList; 467 | buildConfigurations = ( 468 | DEBF4F7E1970FFB90055090F /* Debug */, 469 | DEBF4F7F1970FFB90055090F /* Release */, 470 | ); 471 | defaultConfigurationIsVisible = 0; 472 | }; 473 | /* End XCConfigurationList section */ 474 | }; 475 | rootObject = DEBF4F461970FFB90055090F /* Project object */; 476 | } 477 | -------------------------------------------------------------------------------- /MCAudioFileStream.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MCAudioFileStream/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MCAudioFileStream 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MCAudioFileStream/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MCAudioFileStream 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "MCAudioFileStream.h" 11 | 12 | @interface AppDelegate () 13 | { 14 | @private 15 | MCAudioFileStream *_audioFileStream; 16 | } 17 | @end 18 | 19 | @implementation AppDelegate 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 22 | { 23 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 24 | // Override point for customization after application launch. 25 | self.window.rootViewController = [UIViewController new]; 26 | self.window.backgroundColor = [UIColor whiteColor]; 27 | [self.window makeKeyAndVisible]; 28 | 29 | NSString *path = [[NSBundle mainBundle] pathForResource:@"MP3Sample" ofType:@"mp3"]; 30 | NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; 31 | unsigned long long fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil] fileSize]; 32 | NSError *error = nil; 33 | _audioFileStream = [[MCAudioFileStream alloc] initWithFileType:kAudioFileMP3Type fileSize:fileSize error:&error]; 34 | _audioFileStream.delegate = self; 35 | if (error) 36 | { 37 | _audioFileStream = nil; 38 | NSLog(@"create audio file stream failed, error: %@",[error description]); 39 | } 40 | else 41 | { 42 | NSLog(@"audio file opened."); 43 | if (file) 44 | { 45 | NSUInteger lengthPerRead = 10000; 46 | while (fileSize > 0) 47 | { 48 | NSData *data = [file readDataOfLength:lengthPerRead]; 49 | fileSize -= [data length]; 50 | [_audioFileStream parseData:data error:&error]; 51 | if (error) 52 | { 53 | if (error.code == kAudioFileStreamError_NotOptimized) 54 | { 55 | NSLog(@"audio not optimized."); 56 | } 57 | break; 58 | } 59 | } 60 | NSLog(@"audio format: bitrate = %zd, duration = %lf.",_audioFileStream.bitRate,_audioFileStream.duration); 61 | [_audioFileStream close]; 62 | _audioFileStream = nil; 63 | NSLog(@"audio file closed."); 64 | [file closeFile]; 65 | } 66 | } 67 | 68 | return YES; 69 | } 70 | 71 | - (void)audioFileStreamReadyToProducePackets:(MCAudioFileStream *)audioFileStream 72 | { 73 | NSLog(@"audio ready to produce packets."); 74 | } 75 | 76 | - (void)audioFileStream:(MCAudioFileStream *)audioFileStream audioDataParsed:(NSArray *)audioData 77 | { 78 | NSLog(@"data parsed, should be filled in buffer."); 79 | } 80 | 81 | - (void)applicationWillResignActive:(UIApplication *)application 82 | { 83 | // 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. 84 | // 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. 85 | } 86 | 87 | - (void)applicationDidEnterBackground:(UIApplication *)application 88 | { 89 | // 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. 90 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 91 | } 92 | 93 | - (void)applicationWillEnterForeground:(UIApplication *)application 94 | { 95 | // 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. 96 | } 97 | 98 | - (void)applicationDidBecomeActive:(UIApplication *)application 99 | { 100 | // 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. 101 | } 102 | 103 | - (void)applicationWillTerminate:(UIApplication *)application 104 | { 105 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /MCAudioFileStream/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /MCAudioFileStream/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /MCAudioFileStream/MCAudioFileStream-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | company.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /MCAudioFileStream/MCAudioFileStream-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /MCAudioFileStream/MCAudioFileStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // MCAudioFileStream.h 3 | // MCAudioFileStream 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // https://github.com/msching/MCAudioFileStream 8 | 9 | #import 10 | #import 11 | #import "MCParsedAudioData.h" 12 | 13 | @class MCAudioFileStream; 14 | @protocol MCAudioFileStreamDelegate 15 | @required 16 | - (void)audioFileStream:(MCAudioFileStream *)audioFileStream audioDataParsed:(NSArray *)audioData; 17 | @optional 18 | - (void)audioFileStreamReadyToProducePackets:(MCAudioFileStream *)audioFileStream; 19 | @end 20 | 21 | @interface MCAudioFileStream : NSObject 22 | 23 | @property (nonatomic,assign,readonly) AudioFileTypeID fileType; 24 | @property (nonatomic,assign,readonly) BOOL available; 25 | @property (nonatomic,assign,readonly) BOOL readyToProducePackets; 26 | @property (nonatomic,weak) id delegate; 27 | 28 | @property (nonatomic,assign,readonly) AudioStreamBasicDescription format; 29 | @property (nonatomic,assign,readonly) unsigned long long fileSize; 30 | @property (nonatomic,assign,readonly) NSTimeInterval duration; 31 | @property (nonatomic,assign,readonly) UInt32 bitRate; 32 | @property (nonatomic,assign,readonly) UInt32 maxPacketSize; 33 | @property (nonatomic,assign,readonly) UInt64 audioDataByteCount; 34 | 35 | - (instancetype)initWithFileType:(AudioFileTypeID)fileType fileSize:(unsigned long long)fileSize error:(NSError **)error; 36 | 37 | - (BOOL)parseData:(NSData *)data error:(NSError **)error; 38 | 39 | /** 40 | * seek to timeinterval 41 | * 42 | * @param time On input, timeinterval to seek. 43 | On output, fixed timeinterval. 44 | * 45 | * @return seek byte offset 46 | */ 47 | - (SInt64)seekToTime:(NSTimeInterval *)time; 48 | 49 | - (NSData *)fetchMagicCookie; 50 | 51 | - (void)close; 52 | @end 53 | -------------------------------------------------------------------------------- /MCAudioFileStream/MCAudioFileStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // MCAudioFileStream.m 3 | // MCAudioFileStream 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // https://github.com/msching/MCAudioFileStream 8 | 9 | #import "MCAudioFileStream.h" 10 | 11 | #define BitRateEstimationMaxPackets 5000 12 | #define BitRateEstimationMinPackets 10 13 | 14 | @interface MCAudioFileStream () 15 | { 16 | @private 17 | BOOL _discontinuous; 18 | 19 | AudioFileStreamID _audioFileStreamID; 20 | 21 | SInt64 _dataOffset; 22 | NSTimeInterval _packetDuration; 23 | 24 | UInt64 _processedPacketsCount; 25 | UInt64 _processedPacketsSizeTotal; 26 | } 27 | - (void)handleAudioFileStreamProperty:(AudioFileStreamPropertyID)propertyID; 28 | - (void)handleAudioFileStreamPackets:(const void *)packets 29 | numberOfBytes:(UInt32)numberOfBytes 30 | numberOfPackets:(UInt32)numberOfPackets 31 | packetDescriptions:(AudioStreamPacketDescription *)packetDescriptioins; 32 | @end 33 | 34 | #pragma mark - static callbacks 35 | static void MCSAudioFileStreamPropertyListener(void *inClientData, 36 | AudioFileStreamID inAudioFileStream, 37 | AudioFileStreamPropertyID inPropertyID, 38 | UInt32 *ioFlags) 39 | { 40 | MCAudioFileStream *audioFileStream = (__bridge MCAudioFileStream *)inClientData; 41 | [audioFileStream handleAudioFileStreamProperty:inPropertyID]; 42 | } 43 | 44 | static void MCAudioFileStreamPacketsCallBack(void *inClientData, 45 | UInt32 inNumberBytes, 46 | UInt32 inNumberPackets, 47 | const void *inInputData, 48 | AudioStreamPacketDescription *inPacketDescriptions) 49 | { 50 | MCAudioFileStream *audioFileStream = (__bridge MCAudioFileStream *)inClientData; 51 | [audioFileStream handleAudioFileStreamPackets:inInputData 52 | numberOfBytes:inNumberBytes 53 | numberOfPackets:inNumberPackets 54 | packetDescriptions:inPacketDescriptions]; 55 | } 56 | 57 | #pragma mark - 58 | @implementation MCAudioFileStream 59 | @synthesize fileType = _fileType; 60 | @synthesize readyToProducePackets = _readyToProducePackets; 61 | @dynamic available; 62 | @synthesize delegate = _delegate; 63 | @synthesize duration = _duration; 64 | @synthesize bitRate = _bitRate; 65 | @synthesize format = _format; 66 | @synthesize maxPacketSize = _maxPacketSize; 67 | @synthesize audioDataByteCount = _audioDataByteCount; 68 | 69 | #pragma init & dealloc 70 | - (instancetype)initWithFileType:(AudioFileTypeID)fileType fileSize:(unsigned long long)fileSize error:(NSError **)error 71 | { 72 | self = [super init]; 73 | if (self) 74 | { 75 | _discontinuous = NO; 76 | _fileType = fileType; 77 | _fileSize = fileSize; 78 | [self _openAudioFileStreamWithFileTypeHint:_fileType error:error]; 79 | } 80 | return self; 81 | } 82 | 83 | - (void)dealloc 84 | { 85 | [self _closeAudioFileStream]; 86 | } 87 | 88 | - (void)_errorForOSStatus:(OSStatus)status error:(NSError *__autoreleasing *)outError 89 | { 90 | if (status != noErr && outError != NULL) 91 | { 92 | *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; 93 | } 94 | } 95 | 96 | #pragma mark - open & close 97 | - (BOOL)_openAudioFileStreamWithFileTypeHint:(AudioFileTypeID)fileTypeHint error:(NSError *__autoreleasing *)error 98 | { 99 | OSStatus status = AudioFileStreamOpen((__bridge void *)self, 100 | MCSAudioFileStreamPropertyListener, 101 | MCAudioFileStreamPacketsCallBack, 102 | fileTypeHint, 103 | &_audioFileStreamID); 104 | 105 | if (status != noErr) 106 | { 107 | _audioFileStreamID = NULL; 108 | } 109 | [self _errorForOSStatus:status error:error]; 110 | return status == noErr; 111 | } 112 | 113 | - (void)_closeAudioFileStream 114 | { 115 | if (self.available) 116 | { 117 | AudioFileStreamClose(_audioFileStreamID); 118 | _audioFileStreamID = NULL; 119 | } 120 | } 121 | 122 | - (void)close 123 | { 124 | [self _closeAudioFileStream]; 125 | } 126 | 127 | - (BOOL)available 128 | { 129 | return _audioFileStreamID != NULL; 130 | } 131 | 132 | #pragma mark - actions 133 | - (NSData *)fetchMagicCookie 134 | { 135 | UInt32 cookieSize; 136 | Boolean writable; 137 | OSStatus status = AudioFileStreamGetPropertyInfo(_audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); 138 | if (status != noErr) 139 | { 140 | return nil; 141 | } 142 | 143 | void *cookieData = malloc(cookieSize); 144 | status = AudioFileStreamGetProperty(_audioFileStreamID, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); 145 | if (status != noErr) 146 | { 147 | return nil; 148 | } 149 | 150 | NSData *cookie = [NSData dataWithBytes:cookieData length:cookieSize]; 151 | free(cookieData); 152 | 153 | return cookie; 154 | } 155 | 156 | - (BOOL)parseData:(NSData *)data error:(NSError **)error 157 | { 158 | if (self.readyToProducePackets && _packetDuration == 0) 159 | { 160 | [self _errorForOSStatus:-1 error:error]; 161 | return NO; 162 | } 163 | OSStatus status = AudioFileStreamParseBytes(_audioFileStreamID,(UInt32)[data length],[data bytes],_discontinuous ? kAudioFileStreamParseFlag_Discontinuity : 0); 164 | [self _errorForOSStatus:status error:error]; 165 | return status == noErr; 166 | } 167 | 168 | - (SInt64)seekToTime:(NSTimeInterval *)time 169 | { 170 | SInt64 approximateSeekOffset = _dataOffset + (*time / _duration) * _audioDataByteCount; 171 | SInt64 seekToPacket = floor(*time / _packetDuration); 172 | SInt64 seekByteOffset; 173 | UInt32 ioFlags = 0; 174 | SInt64 outDataByteOffset; 175 | OSStatus status = AudioFileStreamSeek(_audioFileStreamID, seekToPacket, &outDataByteOffset, &ioFlags); 176 | if (status == noErr && !(ioFlags & kAudioFileStreamSeekFlag_OffsetIsEstimated)) 177 | { 178 | *time -= ((approximateSeekOffset - _dataOffset) - outDataByteOffset) * 8.0 / _bitRate; 179 | seekByteOffset = outDataByteOffset + _dataOffset; 180 | } 181 | else 182 | { 183 | _discontinuous = YES; 184 | seekByteOffset = approximateSeekOffset; 185 | } 186 | return seekByteOffset; 187 | } 188 | 189 | #pragma mark - callbacks 190 | - (void)calculateBitRate 191 | { 192 | if (_packetDuration && _processedPacketsCount > BitRateEstimationMinPackets && _processedPacketsCount <= BitRateEstimationMaxPackets) 193 | { 194 | double averagePacketByteSize = _processedPacketsSizeTotal / _processedPacketsCount; 195 | _bitRate = 8.0 * averagePacketByteSize / _packetDuration; 196 | } 197 | } 198 | 199 | - (void)calculateDuration 200 | { 201 | if (_fileSize > 0 && _bitRate > 0) 202 | { 203 | _duration = ((_fileSize - _dataOffset) * 8.0) / _bitRate; 204 | } 205 | } 206 | 207 | - (void)calculatepPacketDuration 208 | { 209 | if (_format.mSampleRate > 0) 210 | { 211 | _packetDuration = _format.mFramesPerPacket / _format.mSampleRate; 212 | } 213 | } 214 | 215 | - (void)handleAudioFileStreamProperty:(AudioFileStreamPropertyID)propertyID 216 | { 217 | if (propertyID == kAudioFileStreamProperty_ReadyToProducePackets) 218 | { 219 | _readyToProducePackets = YES; 220 | _discontinuous = YES; 221 | 222 | UInt32 sizeOfUInt32 = sizeof(_maxPacketSize); 223 | OSStatus status = AudioFileStreamGetProperty(_audioFileStreamID, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &_maxPacketSize); 224 | if (status != noErr || _maxPacketSize == 0) 225 | { 226 | status = AudioFileStreamGetProperty(_audioFileStreamID, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &_maxPacketSize); 227 | } 228 | 229 | if (_delegate && [_delegate respondsToSelector:@selector(audioFileStreamReadyToProducePackets:)]) 230 | { 231 | [_delegate audioFileStreamReadyToProducePackets:self]; 232 | } 233 | } 234 | else if (propertyID == kAudioFileStreamProperty_DataOffset) 235 | { 236 | UInt32 offsetSize = sizeof(_dataOffset); 237 | AudioFileStreamGetProperty(_audioFileStreamID, kAudioFileStreamProperty_DataOffset, &offsetSize, &_dataOffset); 238 | _audioDataByteCount = _fileSize - _dataOffset; 239 | [self calculateDuration]; 240 | } 241 | else if (propertyID == kAudioFileStreamProperty_DataFormat) 242 | { 243 | UInt32 asbdSize = sizeof(_format); 244 | AudioFileStreamGetProperty(_audioFileStreamID, kAudioFileStreamProperty_DataFormat, &asbdSize, &_format); 245 | [self calculatepPacketDuration]; 246 | } 247 | else if (propertyID == kAudioFileStreamProperty_FormatList) 248 | { 249 | Boolean outWriteable; 250 | UInt32 formatListSize; 251 | OSStatus status = AudioFileStreamGetPropertyInfo(_audioFileStreamID, kAudioFileStreamProperty_FormatList, &formatListSize, &outWriteable); 252 | if (status == noErr) 253 | { 254 | AudioFormatListItem *formatList = malloc(formatListSize); 255 | OSStatus status = AudioFileStreamGetProperty(_audioFileStreamID, kAudioFileStreamProperty_FormatList, &formatListSize, formatList); 256 | if (status == noErr) 257 | { 258 | UInt32 supportedFormatsSize; 259 | status = AudioFormatGetPropertyInfo(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &supportedFormatsSize); 260 | if (status != noErr) 261 | { 262 | free(formatList); 263 | return; 264 | } 265 | 266 | UInt32 supportedFormatCount = supportedFormatsSize / sizeof(OSType); 267 | OSType *supportedFormats = (OSType *)malloc(supportedFormatsSize); 268 | status = AudioFormatGetProperty(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &supportedFormatsSize, supportedFormats); 269 | if (status != noErr) 270 | { 271 | free(formatList); 272 | free(supportedFormats); 273 | return; 274 | } 275 | 276 | for (int i = 0; i * sizeof(AudioFormatListItem) < formatListSize; i ++) 277 | { 278 | AudioStreamBasicDescription format = formatList[i].mASBD; 279 | for (UInt32 j = 0; j < supportedFormatCount; ++j) 280 | { 281 | if (format.mFormatID == supportedFormats[j]) 282 | { 283 | _format = format; 284 | [self calculatepPacketDuration]; 285 | break; 286 | } 287 | } 288 | } 289 | free(supportedFormats); 290 | } 291 | free(formatList); 292 | } 293 | } 294 | } 295 | 296 | - (void)handleAudioFileStreamPackets:(const void *)packets 297 | numberOfBytes:(UInt32)numberOfBytes 298 | numberOfPackets:(UInt32)numberOfPackets 299 | packetDescriptions:(AudioStreamPacketDescription *)packetDescriptioins 300 | { 301 | if (_discontinuous) 302 | { 303 | _discontinuous = NO; 304 | } 305 | 306 | if (numberOfBytes == 0 || numberOfPackets == 0) 307 | { 308 | return; 309 | } 310 | 311 | BOOL deletePackDesc = NO; 312 | if (packetDescriptioins == NULL) 313 | { 314 | deletePackDesc = YES; 315 | UInt32 packetSize = numberOfBytes / numberOfPackets; 316 | AudioStreamPacketDescription *descriptions = (AudioStreamPacketDescription *)malloc(sizeof(AudioStreamPacketDescription) * numberOfPackets); 317 | 318 | for (int i = 0; i < numberOfPackets; i++) 319 | { 320 | UInt32 packetOffset = packetSize * i; 321 | descriptions[i].mStartOffset = packetOffset; 322 | descriptions[i].mVariableFramesInPacket = 0; 323 | if (i == numberOfPackets - 1) 324 | { 325 | descriptions[i].mDataByteSize = numberOfBytes - packetOffset; 326 | } 327 | else 328 | { 329 | descriptions[i].mDataByteSize = packetSize; 330 | } 331 | } 332 | packetDescriptioins = descriptions; 333 | } 334 | 335 | NSMutableArray *parsedDataArray = [[NSMutableArray alloc] init]; 336 | for (int i = 0; i < numberOfPackets; ++i) 337 | { 338 | SInt64 packetOffset = packetDescriptioins[i].mStartOffset; 339 | MCParsedAudioData *parsedData = [MCParsedAudioData parsedAudioDataWithBytes:packets + packetOffset 340 | packetDescription:packetDescriptioins[i]]; 341 | 342 | [parsedDataArray addObject:parsedData]; 343 | 344 | if (_processedPacketsCount < BitRateEstimationMaxPackets) 345 | { 346 | _processedPacketsSizeTotal += parsedData.packetDescription.mDataByteSize; 347 | _processedPacketsCount += 1; 348 | [self calculateBitRate]; 349 | [self calculateDuration]; 350 | } 351 | } 352 | 353 | [_delegate audioFileStream:self audioDataParsed:parsedDataArray]; 354 | 355 | if (deletePackDesc) 356 | { 357 | free(packetDescriptioins); 358 | } 359 | } 360 | @end 361 | -------------------------------------------------------------------------------- /MCAudioFileStream/MCParsedAudioData.h: -------------------------------------------------------------------------------- 1 | // 2 | // MCParsedAudioData.h 3 | // MCAudioFileStream 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // https://github.com/msching/MCAudioFileStream 8 | 9 | #import 10 | #import 11 | 12 | @interface MCParsedAudioData : NSObject 13 | 14 | @property (nonatomic,readonly) NSData *data; 15 | @property (nonatomic,readonly) AudioStreamPacketDescription packetDescription; 16 | 17 | + (instancetype)parsedAudioDataWithBytes:(const void *)bytes 18 | packetDescription:(AudioStreamPacketDescription)packetDescription; 19 | @end 20 | -------------------------------------------------------------------------------- /MCAudioFileStream/MCParsedAudioData.m: -------------------------------------------------------------------------------- 1 | // 2 | // MCParsedAudioData.m 3 | // MCAudioFileStream 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // https://github.com/msching/MCAudioFileStream 8 | 9 | #import "MCParsedAudioData.h" 10 | 11 | @implementation MCParsedAudioData 12 | @synthesize data = _data; 13 | @synthesize packetDescription = _packetDescription; 14 | 15 | + (instancetype)parsedAudioDataWithBytes:(const void *)bytes 16 | packetDescription:(AudioStreamPacketDescription)packetDescription 17 | { 18 | return [[self alloc] initWithBytes:bytes 19 | packetDescription:packetDescription]; 20 | } 21 | 22 | - (instancetype)initWithBytes:(const void *)bytes packetDescription:(AudioStreamPacketDescription)packetDescription 23 | { 24 | if (bytes == NULL || packetDescription.mDataByteSize == 0) 25 | { 26 | return nil; 27 | } 28 | 29 | self = [super init]; 30 | if (self) 31 | { 32 | _data = [NSData dataWithBytes:bytes length:packetDescription.mDataByteSize]; 33 | _packetDescription = packetDescription; 34 | } 35 | return self; 36 | } 37 | @end -------------------------------------------------------------------------------- /MCAudioFileStream/MP3Sample.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msching/MCAudioFileStream/833398672189721e0048206bb11e5765063818ed/MCAudioFileStream/MP3Sample.mp3 -------------------------------------------------------------------------------- /MCAudioFileStream/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /MCAudioFileStream/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MCAudioFileStream 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MCAudioFileStreamTests/MCAudioFileStreamTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | company.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /MCAudioFileStreamTests/MCAudioFileStreamTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MCAudioFileStreamTests.m 3 | // MCAudioFileStreamTests 4 | // 5 | // Created by Chengyin on 14-7-12. 6 | // Copyright (c) 2014年 Chengyin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MCAudioFileStreamTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation MCAudioFileStreamTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /MCAudioFileStreamTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MCAudioFileStream 2 | ================= 3 | 4 | a simple wrapper of AudioFileStream 5 | 6 | 一个简单的AudioFileStream封装 7 | 8 | 相关的Blog:http://msching.github.io/blog/2014/07/09/audio-in-ios-3/ --------------------------------------------------------------------------------