├── AUPlayer.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ ├── apple.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── AUPlayer.xcscheme │ │ └── xcschememanagement.plist │ └── xiaokai.zhan.xcuserdatad │ └── xcschemes │ ├── AUPlayer.xcscheme │ └── xcschememanagement.plist ├── AUPlayer ├── AUGraphPlayer.h ├── AUGraphPlayer.m ├── AVAudioSession+RouteUtils.h ├── AVAudioSession+RouteUtils.m ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── LaunchScreen.storyboard ├── ELAudioSession.h ├── ELAudioSession.m ├── Info.plist ├── ViewController.h ├── ViewController.m ├── ViewController.xib ├── main.m ├── resource │ ├── 0fe2a7e9c51012210eaaa1e2b103b1b1.m4a │ └── MiAmor.mp3 └── utils │ ├── CommonUtil.h │ └── CommonUtil.m ├── AUPlayerTests ├── AUPlayerTests.m └── Info.plist └── AUPlayerUITests ├── AUPlayerUITests.m └── Info.plist /AUPlayer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 18E9F5D91E4C781100853E4E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F5D81E4C781100853E4E /* main.m */; }; 11 | 18E9F5DC1E4C781100853E4E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F5DB1E4C781100853E4E /* AppDelegate.m */; }; 12 | 18E9F5DF1E4C781200853E4E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F5DE1E4C781200853E4E /* ViewController.m */; }; 13 | 18E9F5E41E4C781300853E4E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18E9F5E31E4C781300853E4E /* Assets.xcassets */; }; 14 | 18E9F5E71E4C781300853E4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18E9F5E51E4C781300853E4E /* LaunchScreen.storyboard */; }; 15 | 18E9F5F21E4C781300853E4E /* AUPlayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F5F11E4C781300853E4E /* AUPlayerTests.m */; }; 16 | 18E9F5FD1E4C781300853E4E /* AUPlayerUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F5FC1E4C781300853E4E /* AUPlayerUITests.m */; }; 17 | 18E9F60B1E4C78BE00853E4E /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18E9F60A1E4C78BE00853E4E /* ViewController.xib */; }; 18 | 18E9F6111E4C7BF600853E4E /* MiAmor.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 18E9F60D1E4C7BF600853E4E /* MiAmor.mp3 */; }; 19 | 18E9F6121E4C7BF600853E4E /* CommonUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F6101E4C7BF600853E4E /* CommonUtil.m */; }; 20 | 18E9F6151E4C845A00853E4E /* AUGraphPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F6141E4C845A00853E4E /* AUGraphPlayer.m */; }; 21 | 18E9F6281E4C8FB600853E4E /* AVAudioSession+RouteUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F6251E4C8FB600853E4E /* AVAudioSession+RouteUtils.m */; }; 22 | 18E9F6291E4C8FB600853E4E /* ELAudioSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E9F6271E4C8FB600853E4E /* ELAudioSession.m */; }; 23 | 3408774E1F71711100A48BC9 /* 0fe2a7e9c51012210eaaa1e2b103b1b1.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 3408774D1F71711100A48BC9 /* 0fe2a7e9c51012210eaaa1e2b103b1b1.m4a */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | 18E9F5EE1E4C781300853E4E /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 18E9F5CC1E4C781100853E4E /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 18E9F5D31E4C781100853E4E; 32 | remoteInfo = AUPlayer; 33 | }; 34 | 18E9F5F91E4C781300853E4E /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 18E9F5CC1E4C781100853E4E /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 18E9F5D31E4C781100853E4E; 39 | remoteInfo = AUPlayer; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 18E9F5D41E4C781100853E4E /* AUPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AUPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 18E9F5D81E4C781100853E4E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | 18E9F5DA1E4C781100853E4E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 47 | 18E9F5DB1E4C781100853E4E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 48 | 18E9F5DD1E4C781200853E4E /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 49 | 18E9F5DE1E4C781200853E4E /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 50 | 18E9F5E31E4C781300853E4E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 18E9F5E61E4C781300853E4E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 18E9F5E81E4C781300853E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 18E9F5ED1E4C781300853E4E /* AUPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AUPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 18E9F5F11E4C781300853E4E /* AUPlayerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AUPlayerTests.m; sourceTree = ""; }; 55 | 18E9F5F31E4C781300853E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 18E9F5F81E4C781300853E4E /* AUPlayerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AUPlayerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 18E9F5FC1E4C781300853E4E /* AUPlayerUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AUPlayerUITests.m; sourceTree = ""; }; 58 | 18E9F5FE1E4C781300853E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 18E9F60A1E4C78BE00853E4E /* ViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ViewController.xib; sourceTree = ""; }; 60 | 18E9F60D1E4C7BF600853E4E /* MiAmor.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = MiAmor.mp3; sourceTree = ""; }; 61 | 18E9F60F1E4C7BF600853E4E /* CommonUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonUtil.h; sourceTree = ""; }; 62 | 18E9F6101E4C7BF600853E4E /* CommonUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommonUtil.m; sourceTree = ""; }; 63 | 18E9F6131E4C845A00853E4E /* AUGraphPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AUGraphPlayer.h; sourceTree = ""; }; 64 | 18E9F6141E4C845A00853E4E /* AUGraphPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AUGraphPlayer.m; sourceTree = ""; }; 65 | 18E9F6241E4C8FB600853E4E /* AVAudioSession+RouteUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AVAudioSession+RouteUtils.h"; sourceTree = ""; }; 66 | 18E9F6251E4C8FB600853E4E /* AVAudioSession+RouteUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AVAudioSession+RouteUtils.m"; sourceTree = ""; }; 67 | 18E9F6261E4C8FB600853E4E /* ELAudioSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELAudioSession.h; sourceTree = ""; }; 68 | 18E9F6271E4C8FB600853E4E /* ELAudioSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ELAudioSession.m; sourceTree = ""; }; 69 | 3408774D1F71711100A48BC9 /* 0fe2a7e9c51012210eaaa1e2b103b1b1.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = 0fe2a7e9c51012210eaaa1e2b103b1b1.m4a; sourceTree = ""; }; 70 | /* End PBXFileReference section */ 71 | 72 | /* Begin PBXFrameworksBuildPhase section */ 73 | 18E9F5D11E4C781100853E4E /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | ); 78 | runOnlyForDeploymentPostprocessing = 0; 79 | }; 80 | 18E9F5EA1E4C781300853E4E /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | 18E9F5F51E4C781300853E4E /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | /* End PBXFrameworksBuildPhase section */ 95 | 96 | /* Begin PBXGroup section */ 97 | 18E9F5CB1E4C781000853E4E = { 98 | isa = PBXGroup; 99 | children = ( 100 | 18E9F5D61E4C781100853E4E /* AUPlayer */, 101 | 18E9F5F01E4C781300853E4E /* AUPlayerTests */, 102 | 18E9F5FB1E4C781300853E4E /* AUPlayerUITests */, 103 | 18E9F5D51E4C781100853E4E /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 18E9F5D51E4C781100853E4E /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 18E9F5D41E4C781100853E4E /* AUPlayer.app */, 111 | 18E9F5ED1E4C781300853E4E /* AUPlayerTests.xctest */, 112 | 18E9F5F81E4C781300853E4E /* AUPlayerUITests.xctest */, 113 | ); 114 | name = Products; 115 | sourceTree = ""; 116 | }; 117 | 18E9F5D61E4C781100853E4E /* AUPlayer */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 18E9F62A1E4D7A2400853E4E /* AudioSession */, 121 | 18E9F6231E4C8F6700853E4E /* AUPlayer */, 122 | 18E9F60C1E4C7BF600853E4E /* resource */, 123 | 18E9F60E1E4C7BF600853E4E /* utils */, 124 | 18E9F5DA1E4C781100853E4E /* AppDelegate.h */, 125 | 18E9F5DB1E4C781100853E4E /* AppDelegate.m */, 126 | 18E9F5DD1E4C781200853E4E /* ViewController.h */, 127 | 18E9F5DE1E4C781200853E4E /* ViewController.m */, 128 | 18E9F5E31E4C781300853E4E /* Assets.xcassets */, 129 | 18E9F5E51E4C781300853E4E /* LaunchScreen.storyboard */, 130 | 18E9F5E81E4C781300853E4E /* Info.plist */, 131 | 18E9F5D71E4C781100853E4E /* Supporting Files */, 132 | 18E9F60A1E4C78BE00853E4E /* ViewController.xib */, 133 | ); 134 | path = AUPlayer; 135 | sourceTree = ""; 136 | }; 137 | 18E9F5D71E4C781100853E4E /* Supporting Files */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 18E9F5D81E4C781100853E4E /* main.m */, 141 | ); 142 | name = "Supporting Files"; 143 | sourceTree = ""; 144 | }; 145 | 18E9F5F01E4C781300853E4E /* AUPlayerTests */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 18E9F5F11E4C781300853E4E /* AUPlayerTests.m */, 149 | 18E9F5F31E4C781300853E4E /* Info.plist */, 150 | ); 151 | path = AUPlayerTests; 152 | sourceTree = ""; 153 | }; 154 | 18E9F5FB1E4C781300853E4E /* AUPlayerUITests */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 18E9F5FC1E4C781300853E4E /* AUPlayerUITests.m */, 158 | 18E9F5FE1E4C781300853E4E /* Info.plist */, 159 | ); 160 | path = AUPlayerUITests; 161 | sourceTree = ""; 162 | }; 163 | 18E9F60C1E4C7BF600853E4E /* resource */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 3408774D1F71711100A48BC9 /* 0fe2a7e9c51012210eaaa1e2b103b1b1.m4a */, 167 | 18E9F60D1E4C7BF600853E4E /* MiAmor.mp3 */, 168 | ); 169 | path = resource; 170 | sourceTree = ""; 171 | }; 172 | 18E9F60E1E4C7BF600853E4E /* utils */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 18E9F60F1E4C7BF600853E4E /* CommonUtil.h */, 176 | 18E9F6101E4C7BF600853E4E /* CommonUtil.m */, 177 | ); 178 | path = utils; 179 | sourceTree = ""; 180 | }; 181 | 18E9F6231E4C8F6700853E4E /* AUPlayer */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 18E9F6131E4C845A00853E4E /* AUGraphPlayer.h */, 185 | 18E9F6141E4C845A00853E4E /* AUGraphPlayer.m */, 186 | ); 187 | name = AUPlayer; 188 | sourceTree = ""; 189 | }; 190 | 18E9F62A1E4D7A2400853E4E /* AudioSession */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | 18E9F6241E4C8FB600853E4E /* AVAudioSession+RouteUtils.h */, 194 | 18E9F6251E4C8FB600853E4E /* AVAudioSession+RouteUtils.m */, 195 | 18E9F6261E4C8FB600853E4E /* ELAudioSession.h */, 196 | 18E9F6271E4C8FB600853E4E /* ELAudioSession.m */, 197 | ); 198 | name = AudioSession; 199 | sourceTree = ""; 200 | }; 201 | /* End PBXGroup section */ 202 | 203 | /* Begin PBXNativeTarget section */ 204 | 18E9F5D31E4C781100853E4E /* AUPlayer */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 18E9F6011E4C781300853E4E /* Build configuration list for PBXNativeTarget "AUPlayer" */; 207 | buildPhases = ( 208 | 18E9F5D01E4C781100853E4E /* Sources */, 209 | 18E9F5D11E4C781100853E4E /* Frameworks */, 210 | 18E9F5D21E4C781100853E4E /* Resources */, 211 | ); 212 | buildRules = ( 213 | ); 214 | dependencies = ( 215 | ); 216 | name = AUPlayer; 217 | productName = AUPlayer; 218 | productReference = 18E9F5D41E4C781100853E4E /* AUPlayer.app */; 219 | productType = "com.apple.product-type.application"; 220 | }; 221 | 18E9F5EC1E4C781300853E4E /* AUPlayerTests */ = { 222 | isa = PBXNativeTarget; 223 | buildConfigurationList = 18E9F6041E4C781300853E4E /* Build configuration list for PBXNativeTarget "AUPlayerTests" */; 224 | buildPhases = ( 225 | 18E9F5E91E4C781300853E4E /* Sources */, 226 | 18E9F5EA1E4C781300853E4E /* Frameworks */, 227 | 18E9F5EB1E4C781300853E4E /* Resources */, 228 | ); 229 | buildRules = ( 230 | ); 231 | dependencies = ( 232 | 18E9F5EF1E4C781300853E4E /* PBXTargetDependency */, 233 | ); 234 | name = AUPlayerTests; 235 | productName = AUPlayerTests; 236 | productReference = 18E9F5ED1E4C781300853E4E /* AUPlayerTests.xctest */; 237 | productType = "com.apple.product-type.bundle.unit-test"; 238 | }; 239 | 18E9F5F71E4C781300853E4E /* AUPlayerUITests */ = { 240 | isa = PBXNativeTarget; 241 | buildConfigurationList = 18E9F6071E4C781300853E4E /* Build configuration list for PBXNativeTarget "AUPlayerUITests" */; 242 | buildPhases = ( 243 | 18E9F5F41E4C781300853E4E /* Sources */, 244 | 18E9F5F51E4C781300853E4E /* Frameworks */, 245 | 18E9F5F61E4C781300853E4E /* Resources */, 246 | ); 247 | buildRules = ( 248 | ); 249 | dependencies = ( 250 | 18E9F5FA1E4C781300853E4E /* PBXTargetDependency */, 251 | ); 252 | name = AUPlayerUITests; 253 | productName = AUPlayerUITests; 254 | productReference = 18E9F5F81E4C781300853E4E /* AUPlayerUITests.xctest */; 255 | productType = "com.apple.product-type.bundle.ui-testing"; 256 | }; 257 | /* End PBXNativeTarget section */ 258 | 259 | /* Begin PBXProject section */ 260 | 18E9F5CC1E4C781100853E4E /* Project object */ = { 261 | isa = PBXProject; 262 | attributes = { 263 | LastUpgradeCheck = 0820; 264 | ORGANIZATIONNAME = xiaokai.zhan; 265 | TargetAttributes = { 266 | 18E9F5D31E4C781100853E4E = { 267 | CreatedOnToolsVersion = 8.2.1; 268 | DevelopmentTeam = U4BCBA6SZN; 269 | ProvisioningStyle = Automatic; 270 | }; 271 | 18E9F5EC1E4C781300853E4E = { 272 | CreatedOnToolsVersion = 8.2.1; 273 | DevelopmentTeam = MY5GTD35UJ; 274 | ProvisioningStyle = Automatic; 275 | TestTargetID = 18E9F5D31E4C781100853E4E; 276 | }; 277 | 18E9F5F71E4C781300853E4E = { 278 | CreatedOnToolsVersion = 8.2.1; 279 | DevelopmentTeam = MY5GTD35UJ; 280 | ProvisioningStyle = Automatic; 281 | TestTargetID = 18E9F5D31E4C781100853E4E; 282 | }; 283 | }; 284 | }; 285 | buildConfigurationList = 18E9F5CF1E4C781100853E4E /* Build configuration list for PBXProject "AUPlayer" */; 286 | compatibilityVersion = "Xcode 3.2"; 287 | developmentRegion = English; 288 | hasScannedForEncodings = 0; 289 | knownRegions = ( 290 | en, 291 | Base, 292 | ); 293 | mainGroup = 18E9F5CB1E4C781000853E4E; 294 | productRefGroup = 18E9F5D51E4C781100853E4E /* Products */; 295 | projectDirPath = ""; 296 | projectRoot = ""; 297 | targets = ( 298 | 18E9F5D31E4C781100853E4E /* AUPlayer */, 299 | 18E9F5EC1E4C781300853E4E /* AUPlayerTests */, 300 | 18E9F5F71E4C781300853E4E /* AUPlayerUITests */, 301 | ); 302 | }; 303 | /* End PBXProject section */ 304 | 305 | /* Begin PBXResourcesBuildPhase section */ 306 | 18E9F5D21E4C781100853E4E /* Resources */ = { 307 | isa = PBXResourcesBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | 18E9F5E71E4C781300853E4E /* LaunchScreen.storyboard in Resources */, 311 | 18E9F6111E4C7BF600853E4E /* MiAmor.mp3 in Resources */, 312 | 18E9F60B1E4C78BE00853E4E /* ViewController.xib in Resources */, 313 | 18E9F5E41E4C781300853E4E /* Assets.xcassets in Resources */, 314 | 3408774E1F71711100A48BC9 /* 0fe2a7e9c51012210eaaa1e2b103b1b1.m4a in Resources */, 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | }; 318 | 18E9F5EB1E4C781300853E4E /* Resources */ = { 319 | isa = PBXResourcesBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | }; 325 | 18E9F5F61E4C781300853E4E /* Resources */ = { 326 | isa = PBXResourcesBuildPhase; 327 | buildActionMask = 2147483647; 328 | files = ( 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | /* End PBXResourcesBuildPhase section */ 333 | 334 | /* Begin PBXSourcesBuildPhase section */ 335 | 18E9F5D01E4C781100853E4E /* Sources */ = { 336 | isa = PBXSourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 18E9F5DF1E4C781200853E4E /* ViewController.m in Sources */, 340 | 18E9F5DC1E4C781100853E4E /* AppDelegate.m in Sources */, 341 | 18E9F6121E4C7BF600853E4E /* CommonUtil.m in Sources */, 342 | 18E9F5D91E4C781100853E4E /* main.m in Sources */, 343 | 18E9F6281E4C8FB600853E4E /* AVAudioSession+RouteUtils.m in Sources */, 344 | 18E9F6151E4C845A00853E4E /* AUGraphPlayer.m in Sources */, 345 | 18E9F6291E4C8FB600853E4E /* ELAudioSession.m in Sources */, 346 | ); 347 | runOnlyForDeploymentPostprocessing = 0; 348 | }; 349 | 18E9F5E91E4C781300853E4E /* Sources */ = { 350 | isa = PBXSourcesBuildPhase; 351 | buildActionMask = 2147483647; 352 | files = ( 353 | 18E9F5F21E4C781300853E4E /* AUPlayerTests.m in Sources */, 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | 18E9F5F41E4C781300853E4E /* Sources */ = { 358 | isa = PBXSourcesBuildPhase; 359 | buildActionMask = 2147483647; 360 | files = ( 361 | 18E9F5FD1E4C781300853E4E /* AUPlayerUITests.m in Sources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | /* End PBXSourcesBuildPhase section */ 366 | 367 | /* Begin PBXTargetDependency section */ 368 | 18E9F5EF1E4C781300853E4E /* PBXTargetDependency */ = { 369 | isa = PBXTargetDependency; 370 | target = 18E9F5D31E4C781100853E4E /* AUPlayer */; 371 | targetProxy = 18E9F5EE1E4C781300853E4E /* PBXContainerItemProxy */; 372 | }; 373 | 18E9F5FA1E4C781300853E4E /* PBXTargetDependency */ = { 374 | isa = PBXTargetDependency; 375 | target = 18E9F5D31E4C781100853E4E /* AUPlayer */; 376 | targetProxy = 18E9F5F91E4C781300853E4E /* PBXContainerItemProxy */; 377 | }; 378 | /* End PBXTargetDependency section */ 379 | 380 | /* Begin PBXVariantGroup section */ 381 | 18E9F5E51E4C781300853E4E /* LaunchScreen.storyboard */ = { 382 | isa = PBXVariantGroup; 383 | children = ( 384 | 18E9F5E61E4C781300853E4E /* Base */, 385 | ); 386 | name = LaunchScreen.storyboard; 387 | sourceTree = ""; 388 | }; 389 | /* End PBXVariantGroup section */ 390 | 391 | /* Begin XCBuildConfiguration section */ 392 | 18E9F5FF1E4C781300853E4E /* Debug */ = { 393 | isa = XCBuildConfiguration; 394 | buildSettings = { 395 | ALWAYS_SEARCH_USER_PATHS = NO; 396 | CLANG_ANALYZER_NONNULL = YES; 397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 398 | CLANG_CXX_LIBRARY = "libc++"; 399 | CLANG_ENABLE_MODULES = YES; 400 | CLANG_ENABLE_OBJC_ARC = YES; 401 | CLANG_WARN_BOOL_CONVERSION = YES; 402 | CLANG_WARN_CONSTANT_CONVERSION = YES; 403 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 404 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 405 | CLANG_WARN_EMPTY_BODY = YES; 406 | CLANG_WARN_ENUM_CONVERSION = YES; 407 | CLANG_WARN_INFINITE_RECURSION = YES; 408 | CLANG_WARN_INT_CONVERSION = YES; 409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 410 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 411 | CLANG_WARN_UNREACHABLE_CODE = YES; 412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 413 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 414 | COPY_PHASE_STRIP = NO; 415 | DEBUG_INFORMATION_FORMAT = dwarf; 416 | ENABLE_STRICT_OBJC_MSGSEND = YES; 417 | ENABLE_TESTABILITY = YES; 418 | GCC_C_LANGUAGE_STANDARD = gnu99; 419 | GCC_DYNAMIC_NO_PIC = NO; 420 | GCC_NO_COMMON_BLOCKS = YES; 421 | GCC_OPTIMIZATION_LEVEL = 0; 422 | GCC_PREPROCESSOR_DEFINITIONS = ( 423 | "DEBUG=1", 424 | "$(inherited)", 425 | ); 426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 428 | GCC_WARN_UNDECLARED_SELECTOR = YES; 429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 430 | GCC_WARN_UNUSED_FUNCTION = YES; 431 | GCC_WARN_UNUSED_VARIABLE = YES; 432 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 433 | MTL_ENABLE_DEBUG_INFO = YES; 434 | ONLY_ACTIVE_ARCH = YES; 435 | SDKROOT = iphoneos; 436 | }; 437 | name = Debug; 438 | }; 439 | 18E9F6001E4C781300853E4E /* Release */ = { 440 | isa = XCBuildConfiguration; 441 | buildSettings = { 442 | ALWAYS_SEARCH_USER_PATHS = NO; 443 | CLANG_ANALYZER_NONNULL = YES; 444 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 445 | CLANG_CXX_LIBRARY = "libc++"; 446 | CLANG_ENABLE_MODULES = YES; 447 | CLANG_ENABLE_OBJC_ARC = YES; 448 | CLANG_WARN_BOOL_CONVERSION = YES; 449 | CLANG_WARN_CONSTANT_CONVERSION = YES; 450 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 451 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 452 | CLANG_WARN_EMPTY_BODY = YES; 453 | CLANG_WARN_ENUM_CONVERSION = YES; 454 | CLANG_WARN_INFINITE_RECURSION = YES; 455 | CLANG_WARN_INT_CONVERSION = YES; 456 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 457 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 458 | CLANG_WARN_UNREACHABLE_CODE = YES; 459 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 460 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 461 | COPY_PHASE_STRIP = NO; 462 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 463 | ENABLE_NS_ASSERTIONS = NO; 464 | ENABLE_STRICT_OBJC_MSGSEND = YES; 465 | GCC_C_LANGUAGE_STANDARD = gnu99; 466 | GCC_NO_COMMON_BLOCKS = YES; 467 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 468 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 469 | GCC_WARN_UNDECLARED_SELECTOR = YES; 470 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 471 | GCC_WARN_UNUSED_FUNCTION = YES; 472 | GCC_WARN_UNUSED_VARIABLE = YES; 473 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 474 | MTL_ENABLE_DEBUG_INFO = NO; 475 | SDKROOT = iphoneos; 476 | VALIDATE_PRODUCT = YES; 477 | }; 478 | name = Release; 479 | }; 480 | 18E9F6021E4C781300853E4E /* Debug */ = { 481 | isa = XCBuildConfiguration; 482 | buildSettings = { 483 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 484 | DEVELOPMENT_TEAM = U4BCBA6SZN; 485 | INFOPLIST_FILE = AUPlayer/Info.plist; 486 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 487 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 488 | PRODUCT_BUNDLE_IDENTIFIER = com.audio.encoder.PhuketTour; 489 | PRODUCT_NAME = "$(TARGET_NAME)"; 490 | }; 491 | name = Debug; 492 | }; 493 | 18E9F6031E4C781300853E4E /* Release */ = { 494 | isa = XCBuildConfiguration; 495 | buildSettings = { 496 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 497 | DEVELOPMENT_TEAM = U4BCBA6SZN; 498 | INFOPLIST_FILE = AUPlayer/Info.plist; 499 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 500 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 501 | PRODUCT_BUNDLE_IDENTIFIER = com.audio.encoder.PhuketTour; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | }; 504 | name = Release; 505 | }; 506 | 18E9F6051E4C781300853E4E /* Debug */ = { 507 | isa = XCBuildConfiguration; 508 | buildSettings = { 509 | BUNDLE_LOADER = "$(TEST_HOST)"; 510 | DEVELOPMENT_TEAM = MY5GTD35UJ; 511 | INFOPLIST_FILE = AUPlayerTests/Info.plist; 512 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 513 | PRODUCT_BUNDLE_IDENTIFIER = com.phuket.tour.audio.player.AUPlayerTests; 514 | PRODUCT_NAME = "$(TARGET_NAME)"; 515 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AUPlayer.app/AUPlayer"; 516 | }; 517 | name = Debug; 518 | }; 519 | 18E9F6061E4C781300853E4E /* Release */ = { 520 | isa = XCBuildConfiguration; 521 | buildSettings = { 522 | BUNDLE_LOADER = "$(TEST_HOST)"; 523 | DEVELOPMENT_TEAM = MY5GTD35UJ; 524 | INFOPLIST_FILE = AUPlayerTests/Info.plist; 525 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 526 | PRODUCT_BUNDLE_IDENTIFIER = com.phuket.tour.audio.player.AUPlayerTests; 527 | PRODUCT_NAME = "$(TARGET_NAME)"; 528 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AUPlayer.app/AUPlayer"; 529 | }; 530 | name = Release; 531 | }; 532 | 18E9F6081E4C781300853E4E /* Debug */ = { 533 | isa = XCBuildConfiguration; 534 | buildSettings = { 535 | DEVELOPMENT_TEAM = MY5GTD35UJ; 536 | INFOPLIST_FILE = AUPlayerUITests/Info.plist; 537 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 538 | PRODUCT_BUNDLE_IDENTIFIER = com.phuket.tour.audio.player.AUPlayerUITests; 539 | PRODUCT_NAME = "$(TARGET_NAME)"; 540 | TEST_TARGET_NAME = AUPlayer; 541 | }; 542 | name = Debug; 543 | }; 544 | 18E9F6091E4C781300853E4E /* Release */ = { 545 | isa = XCBuildConfiguration; 546 | buildSettings = { 547 | DEVELOPMENT_TEAM = MY5GTD35UJ; 548 | INFOPLIST_FILE = AUPlayerUITests/Info.plist; 549 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 550 | PRODUCT_BUNDLE_IDENTIFIER = com.phuket.tour.audio.player.AUPlayerUITests; 551 | PRODUCT_NAME = "$(TARGET_NAME)"; 552 | TEST_TARGET_NAME = AUPlayer; 553 | }; 554 | name = Release; 555 | }; 556 | /* End XCBuildConfiguration section */ 557 | 558 | /* Begin XCConfigurationList section */ 559 | 18E9F5CF1E4C781100853E4E /* Build configuration list for PBXProject "AUPlayer" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | 18E9F5FF1E4C781300853E4E /* Debug */, 563 | 18E9F6001E4C781300853E4E /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | 18E9F6011E4C781300853E4E /* Build configuration list for PBXNativeTarget "AUPlayer" */ = { 569 | isa = XCConfigurationList; 570 | buildConfigurations = ( 571 | 18E9F6021E4C781300853E4E /* Debug */, 572 | 18E9F6031E4C781300853E4E /* Release */, 573 | ); 574 | defaultConfigurationIsVisible = 0; 575 | defaultConfigurationName = Release; 576 | }; 577 | 18E9F6041E4C781300853E4E /* Build configuration list for PBXNativeTarget "AUPlayerTests" */ = { 578 | isa = XCConfigurationList; 579 | buildConfigurations = ( 580 | 18E9F6051E4C781300853E4E /* Debug */, 581 | 18E9F6061E4C781300853E4E /* Release */, 582 | ); 583 | defaultConfigurationIsVisible = 0; 584 | defaultConfigurationName = Release; 585 | }; 586 | 18E9F6071E4C781300853E4E /* Build configuration list for PBXNativeTarget "AUPlayerUITests" */ = { 587 | isa = XCConfigurationList; 588 | buildConfigurations = ( 589 | 18E9F6081E4C781300853E4E /* Debug */, 590 | 18E9F6091E4C781300853E4E /* Release */, 591 | ); 592 | defaultConfigurationIsVisible = 0; 593 | defaultConfigurationName = Release; 594 | }; 595 | /* End XCConfigurationList section */ 596 | }; 597 | rootObject = 18E9F5CC1E4C781100853E4E /* Project object */; 598 | } 599 | -------------------------------------------------------------------------------- /AUPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AUPlayer.xcodeproj/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /AUPlayer.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/AUPlayer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /AUPlayer.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AUPlayer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 18E9F5D31E4C781100853E4E 16 | 17 | primary 18 | 19 | 20 | 18E9F5EC1E4C781300853E4E 21 | 22 | primary 23 | 24 | 25 | 18E9F5F71E4C781300853E4E 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AUPlayer.xcodeproj/xcuserdata/xiaokai.zhan.xcuserdatad/xcschemes/AUPlayer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /AUPlayer.xcodeproj/xcuserdata/xiaokai.zhan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AUPlayer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 18E9F5D31E4C781100853E4E 16 | 17 | primary 18 | 19 | 20 | 18E9F5EC1E4C781300853E4E 21 | 22 | primary 23 | 24 | 25 | 18E9F5F71E4C781300853E4E 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AUPlayer/AUGraphPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // AUGraphPlayer.h 3 | // AUPlayer 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AUGraphPlayer : NSObject 12 | 13 | - (id) initWithFilePath:(NSString*) path; 14 | 15 | - (BOOL)play; 16 | 17 | - (void)stop; 18 | 19 | - (void) setInputSource:(BOOL) isAcc; 20 | @end 21 | -------------------------------------------------------------------------------- /AUPlayer/AUGraphPlayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // AUGraphPlayer.m 3 | // AUPlayer 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import "AUGraphPlayer.h" 10 | #import 11 | #import 12 | #import "ELAudioSession.h" 13 | 14 | @implementation AUGraphPlayer 15 | { 16 | AUGraph mPlayerGraph; 17 | AUNode mPlayerNode; 18 | AUNode mSplitterNode; 19 | AudioUnit mSplitterUnit; 20 | AUNode mAccMixerNode; 21 | AudioUnit mAccMixerUnit; 22 | AUNode mVocalMixerNode; 23 | AudioUnit mVocalMixerUnit; 24 | AudioUnit mPlayerUnit; 25 | AUNode mPlayerIONode; 26 | AudioUnit mPlayerIOUnit; 27 | NSURL* _playPath; 28 | } 29 | 30 | - (id) initWithFilePath:(NSString*) path 31 | { 32 | self = [super init]; 33 | if(self) { 34 | [[ELAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord]; 35 | [[ELAudioSession sharedInstance] setPreferredSampleRate:44100]; 36 | [[ELAudioSession sharedInstance] setActive:YES]; 37 | [[ELAudioSession sharedInstance] addRouteChangeListener]; 38 | [self addAudioSessionInterruptedObserver]; 39 | _playPath = [NSURL URLWithString:path]; 40 | [self initializePlayGraph]; 41 | } 42 | return self; 43 | } 44 | 45 | 46 | - (BOOL)play 47 | { 48 | OSStatus status = AUGraphStart(mPlayerGraph); 49 | CheckStatus(status, @"Could not start AUGraph", YES); 50 | 51 | return YES; 52 | } 53 | 54 | - (void)stop 55 | { 56 | 57 | Boolean isRunning = false; 58 | OSStatus status = AUGraphIsRunning(mPlayerGraph, &isRunning); 59 | if (isRunning) 60 | { 61 | status = AUGraphStop(mPlayerGraph); 62 | CheckStatus(status, @"Could not stop AUGraph", YES); 63 | } 64 | } 65 | 66 | - (void) initializePlayGraph; 67 | { 68 | OSStatus status = noErr; 69 | //1:构造AUGraph 70 | status = NewAUGraph(&mPlayerGraph); 71 | CheckStatus(status, @"Could not create a new AUGraph", YES); 72 | //2-1:添加IONode 73 | AudioComponentDescription ioDescription; 74 | bzero(&ioDescription, sizeof(ioDescription)); 75 | ioDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 76 | ioDescription.componentType = kAudioUnitType_Output; 77 | ioDescription.componentSubType = kAudioUnitSubType_RemoteIO; 78 | status = AUGraphAddNode(mPlayerGraph, &ioDescription, &mPlayerIONode); 79 | CheckStatus(status, @"Could not add I/O node to AUGraph", YES); 80 | //2-2:添加PlayerNode 81 | AudioComponentDescription playerDescription; 82 | bzero(&playerDescription, sizeof(playerDescription)); 83 | playerDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 84 | playerDescription.componentType = kAudioUnitType_Generator; 85 | playerDescription.componentSubType = kAudioUnitSubType_AudioFilePlayer; 86 | status = AUGraphAddNode(mPlayerGraph, &playerDescription, &mPlayerNode); 87 | CheckStatus(status, @"Could not add Player node to AUGraph", YES); 88 | //2-3:添加Splitter 89 | AudioComponentDescription splitterDescription; 90 | bzero(&splitterDescription, sizeof(splitterDescription)); 91 | splitterDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 92 | splitterDescription.componentType = kAudioUnitType_FormatConverter; 93 | splitterDescription.componentSubType = kAudioUnitSubType_Splitter; 94 | status = AUGraphAddNode(mPlayerGraph, &splitterDescription, &mSplitterNode); 95 | CheckStatus(status, @"Could not add Splitter node to AUGraph", YES); 96 | //2-4:添加两个Mixer 97 | AudioComponentDescription mixerDescription; 98 | bzero(&mixerDescription, sizeof(mixerDescription)); 99 | mixerDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 100 | mixerDescription.componentType = kAudioUnitType_Mixer; 101 | mixerDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer; 102 | status = AUGraphAddNode(mPlayerGraph, &mixerDescription, &mVocalMixerNode); 103 | CheckStatus(status, @"Could not add VocalMixer node to AUGraph", YES); 104 | status = AUGraphAddNode(mPlayerGraph, &mixerDescription, &mAccMixerNode); 105 | CheckStatus(status, @"Could not add AccMixer node to AUGraph", YES); 106 | 107 | //3:打开Graph, 只有真正的打开了Graph才会实例化每一个Node 108 | status = AUGraphOpen(mPlayerGraph); 109 | CheckStatus(status, @"Could not open AUGraph", YES); 110 | //4-1:获取出IONode的AudioUnit 111 | status = AUGraphNodeInfo(mPlayerGraph, mPlayerIONode, NULL, &mPlayerIOUnit); 112 | CheckStatus(status, @"Could not retrieve node info for I/O node", YES); 113 | //4-2:获取出PlayerNode的AudioUnit 114 | status = AUGraphNodeInfo(mPlayerGraph, mPlayerNode, NULL, &mPlayerUnit); 115 | CheckStatus(status, @"Could not retrieve node info for Player node", YES); 116 | //4-3:获取出PlayerNode的AudioUnit 117 | status = AUGraphNodeInfo(mPlayerGraph, mSplitterNode, NULL, &mSplitterUnit); 118 | CheckStatus(status, @"Could not retrieve node info for Splitter node", YES); 119 | //4-4:获取出VocalMixer的AudioUnit 120 | status = AUGraphNodeInfo(mPlayerGraph, mVocalMixerNode, NULL, &mVocalMixerUnit); 121 | CheckStatus(status, @"Could not retrieve node info for VocalMixer node", YES); 122 | //4-5:获取出AccMixer的AudioUnit 123 | status = AUGraphNodeInfo(mPlayerGraph, mAccMixerNode, NULL, &mAccMixerUnit); 124 | CheckStatus(status, @"Could not retrieve node info for AccMixer node", YES); 125 | 126 | //5:给AudioUnit设置参数 127 | AudioStreamBasicDescription stereoStreamFormat; 128 | UInt32 bytesPerSample = sizeof(Float32); 129 | bzero(&stereoStreamFormat, sizeof(stereoStreamFormat)); 130 | stereoStreamFormat.mFormatID = kAudioFormatLinearPCM; 131 | stereoStreamFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; 132 | stereoStreamFormat.mBytesPerPacket = bytesPerSample; 133 | stereoStreamFormat.mFramesPerPacket = 1; 134 | stereoStreamFormat.mBytesPerFrame = bytesPerSample; 135 | stereoStreamFormat.mChannelsPerFrame = 2; // 2 indicates stereo 136 | stereoStreamFormat.mBitsPerChannel = 8 * bytesPerSample; 137 | stereoStreamFormat.mSampleRate = 48000.0; 138 | status = AudioUnitSetProperty(mPlayerIOUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &stereoStreamFormat, sizeof(stereoStreamFormat)); 139 | CheckStatus(status, @"set remote IO output element stream format ", YES); 140 | status = AudioUnitSetProperty( 141 | mPlayerUnit, 142 | kAudioUnitProperty_StreamFormat, 143 | kAudioUnitScope_Output, 144 | 0, 145 | &stereoStreamFormat, 146 | sizeof (stereoStreamFormat) 147 | ); 148 | CheckStatus(status, @"Could not Set StreamFormat for Player Unit", YES); 149 | 150 | //5-2配置Splitter的属性 151 | status = AudioUnitSetProperty(mSplitterUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 152 | 0, &stereoStreamFormat, sizeof(stereoStreamFormat)); 153 | CheckStatus(status, @"Could not Set StreamFormat for Splitter Unit", YES); 154 | status = AudioUnitSetProperty(mSplitterUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 155 | 0, &stereoStreamFormat, sizeof(stereoStreamFormat)); 156 | CheckStatus(status, @"Could not Set StreamFormat for Splitter Unit", YES); 157 | //5-3 配置VocalMixerUnit的属性 158 | status = AudioUnitSetProperty(mVocalMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 159 | 0, &stereoStreamFormat, sizeof(stereoStreamFormat)); 160 | CheckStatus(status, @"Could not Set StreamFormat for VocalMixer Unit", YES); 161 | status = AudioUnitSetProperty(mVocalMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 162 | 0, &stereoStreamFormat, sizeof(stereoStreamFormat)); 163 | CheckStatus(status, @"Could not Set StreamFormat for VocalMixer Unit", YES); 164 | int mixerElementCount = 1; 165 | status = AudioUnitSetProperty(mVocalMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, 166 | &mixerElementCount, sizeof(mixerElementCount)); 167 | //5-4 配置AccMixerUnit的属性 168 | status = AudioUnitSetProperty(mAccMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 169 | 0, &stereoStreamFormat, sizeof(stereoStreamFormat)); 170 | CheckStatus(status, @"Could not Set StreamFormat for AccMixer Unit", YES); 171 | status = AudioUnitSetProperty(mAccMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 172 | 0, &stereoStreamFormat, sizeof(stereoStreamFormat)); 173 | CheckStatus(status, @"Could not Set StreamFormat for AccMixer Unit", YES); 174 | mixerElementCount = 2; 175 | status = AudioUnitSetProperty(mAccMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, 176 | &mixerElementCount, sizeof(mixerElementCount)); 177 | 178 | [self setInputSource:NO]; 179 | //6:连接起Node来 180 | AUGraphConnectNodeInput(mPlayerGraph, mPlayerNode, 0, mSplitterNode, 0); 181 | CheckStatus(status, @"Player Node Connect To IONode", YES); 182 | AUGraphConnectNodeInput(mPlayerGraph, mSplitterNode, 0, mVocalMixerNode, 0); 183 | CheckStatus(status, @"Player Node Connect To IONode", YES); 184 | AUGraphConnectNodeInput(mPlayerGraph, mSplitterNode, 1, mAccMixerNode, 0); 185 | CheckStatus(status, @"Player Node Connect To IONode", YES); 186 | AUGraphConnectNodeInput(mPlayerGraph, mVocalMixerNode, 0, mAccMixerNode, 1); 187 | CheckStatus(status, @"Player Node Connect To IONode", YES); 188 | AUGraphConnectNodeInput(mPlayerGraph, mAccMixerNode, 0, mPlayerIONode, 0); 189 | CheckStatus(status, @"Player Node Connect To IONode", YES); 190 | //7:初始化Graph 191 | status = AUGraphInitialize(mPlayerGraph); 192 | CheckStatus(status, @"Couldn't Initialize the graph", YES); 193 | //8:显示Graph结构 194 | CAShow(mPlayerGraph); 195 | //9:只有对Graph进行Initialize之后才可以设置AudioPlayer的参数 196 | [self setUpFilePlayer]; 197 | } 198 | 199 | - (void) setInputSource:(BOOL) isAcc 200 | { 201 | OSStatus status; 202 | AudioUnitParameterValue value; 203 | status = AudioUnitGetParameter(mVocalMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, &value); 204 | CheckStatus(status, @"get parameter fail", YES); 205 | NSLog(@"Vocal Mixer %lf", value); 206 | status = AudioUnitGetParameter(mAccMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, &value); 207 | CheckStatus(status, @"get parameter fail", YES); 208 | NSLog(@"Acc Mixer 0 %lf", value); 209 | status = AudioUnitGetParameter(mAccMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 1, &value); 210 | CheckStatus(status, @"get parameter fail", YES); 211 | NSLog(@"Acc Mixer 1 %lf", value); 212 | 213 | // status = AudioUnitSetParameter(mVocalMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, 1.0, 0); 214 | // CheckStatus(status, @"set parameter fail", YES); 215 | if(isAcc) { 216 | status = AudioUnitSetParameter(mAccMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, 0.1, 0); 217 | CheckStatus(status, @"set parameter fail", YES); 218 | status = AudioUnitSetParameter(mAccMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 1, 1, 0); 219 | CheckStatus(status, @"set parameter fail", YES); 220 | } else { 221 | status = AudioUnitSetParameter(mAccMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, 1, 0); 222 | CheckStatus(status, @"set parameter fail", YES); 223 | status = AudioUnitSetParameter(mAccMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 1, 0.1, 0); 224 | CheckStatus(status, @"set parameter fail", YES); 225 | } 226 | } 227 | 228 | - (void) setUpFilePlayer; 229 | { 230 | OSStatus status = noErr; 231 | AudioFileID musicFile; 232 | CFURLRef songURL = (__bridge CFURLRef) _playPath; 233 | // open the input audio file 234 | status = AudioFileOpenURL(songURL, kAudioFileReadPermission, 0, &musicFile); 235 | CheckStatus(status, @"Open AudioFile... ", YES); 236 | 237 | 238 | // tell the file player unit to load the file we want to play 239 | status = AudioUnitSetProperty(mPlayerUnit, kAudioUnitProperty_ScheduledFileIDs, 240 | kAudioUnitScope_Global, 0, &musicFile, sizeof(musicFile)); 241 | CheckStatus(status, @"Tell AudioFile Player Unit Load Which File... ", YES); 242 | 243 | 244 | 245 | AudioStreamBasicDescription fileASBD; 246 | // get the audio data format from the file 247 | UInt32 propSize = sizeof(fileASBD); 248 | status = AudioFileGetProperty(musicFile, kAudioFilePropertyDataFormat, 249 | &propSize, &fileASBD); 250 | CheckStatus(status, @"get the audio data format from the file... ", YES); 251 | UInt64 nPackets; 252 | UInt32 propsize = sizeof(nPackets); 253 | AudioFileGetProperty(musicFile, kAudioFilePropertyAudioDataPacketCount, 254 | &propsize, &nPackets); 255 | // tell the file player AU to play the entire file 256 | ScheduledAudioFileRegion rgn; 257 | memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp)); 258 | rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid; 259 | rgn.mTimeStamp.mSampleTime = 0; 260 | rgn.mCompletionProc = NULL; 261 | rgn.mCompletionProcUserData = NULL; 262 | rgn.mAudioFile = musicFile; 263 | rgn.mLoopCount = 0; 264 | rgn.mStartFrame = 0; 265 | rgn.mFramesToPlay = (UInt32)nPackets * fileASBD.mFramesPerPacket; 266 | status = AudioUnitSetProperty(mPlayerUnit, kAudioUnitProperty_ScheduledFileRegion, 267 | kAudioUnitScope_Global, 0,&rgn, sizeof(rgn)); 268 | CheckStatus(status, @"Set Region... ", YES); 269 | 270 | 271 | // prime the file player AU with default values 272 | UInt32 defaultVal = 0; 273 | status = AudioUnitSetProperty(mPlayerUnit, kAudioUnitProperty_ScheduledFilePrime, 274 | kAudioUnitScope_Global, 0, &defaultVal, sizeof(defaultVal)); 275 | CheckStatus(status, @"Prime Player Unit With Default Value... ", YES); 276 | 277 | 278 | // tell the file player AU when to start playing (-1 sample time means next render cycle) 279 | AudioTimeStamp startTime; 280 | memset (&startTime, 0, sizeof(startTime)); 281 | startTime.mFlags = kAudioTimeStampSampleTimeValid; 282 | startTime.mSampleTime = -1; 283 | status = AudioUnitSetProperty(mPlayerUnit, kAudioUnitProperty_ScheduleStartTimeStamp, 284 | kAudioUnitScope_Global, 0, &startTime, sizeof(startTime)); 285 | CheckStatus(status, @"set Player Unit Start Time... ", YES); 286 | } 287 | 288 | // AudioSession 被打断的通知 289 | - (void)addAudioSessionInterruptedObserver 290 | { 291 | [self removeAudioSessionInterruptedObserver]; 292 | [[NSNotificationCenter defaultCenter] addObserver:self 293 | selector:@selector(onNotificationAudioInterrupted:) 294 | name:AVAudioSessionInterruptionNotification 295 | object:[AVAudioSession sharedInstance]]; 296 | } 297 | 298 | - (void)removeAudioSessionInterruptedObserver 299 | { 300 | [[NSNotificationCenter defaultCenter] removeObserver:self 301 | name:AVAudioSessionInterruptionNotification 302 | object:nil]; 303 | } 304 | 305 | - (void)onNotificationAudioInterrupted:(NSNotification *)sender { 306 | AVAudioSessionInterruptionType interruptionType = [[[sender userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue]; 307 | switch (interruptionType) { 308 | case AVAudioSessionInterruptionTypeBegan: 309 | [self stop]; 310 | break; 311 | case AVAudioSessionInterruptionTypeEnded: 312 | [self play]; 313 | break; 314 | default: 315 | break; 316 | } 317 | } 318 | 319 | static void CheckStatus(OSStatus status, NSString *message, BOOL fatal) 320 | { 321 | if(status != noErr) 322 | { 323 | char fourCC[16]; 324 | *(UInt32 *)fourCC = CFSwapInt32HostToBig(status); 325 | fourCC[4] = '\0'; 326 | 327 | if(isprint(fourCC[0]) && isprint(fourCC[1]) && isprint(fourCC[2]) && isprint(fourCC[3])) 328 | NSLog(@"%@: %s", message, fourCC); 329 | else 330 | NSLog(@"%@: %d", message, (int)status); 331 | 332 | if(fatal) 333 | exit(-1); 334 | } 335 | } 336 | 337 | @end 338 | -------------------------------------------------------------------------------- /AUPlayer/AVAudioSession+RouteUtils.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface AVAudioSession (RouteUtils) 4 | 5 | - (BOOL)usingBlueTooth; 6 | 7 | - (BOOL)usingWiredMicrophone; 8 | 9 | - (BOOL)shouldShowEarphoneAlert; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /AUPlayer/AVAudioSession+RouteUtils.m: -------------------------------------------------------------------------------- 1 | #import "AVAudioSession+RouteUtils.h" 2 | 3 | 4 | // /* input port types */ 5 | // AVF_EXPORT NSString *const AVAudioSessionPortLineIn NS_AVAILABLE_IOS(6_0); /* Line level input on a dock connector */ 6 | // AVF_EXPORT NSString *const AVAudioSessionPortBuiltInMic NS_AVAILABLE_IOS(6_0); /* Built-in microphone on an iOS device */ 7 | // AVF_EXPORT NSString *const AVAudioSessionPortHeadsetMic NS_AVAILABLE_IOS(6_0); /* Microphone on a wired headset. Headset refers to an 8 | // 9 | // /* output port types */ 10 | // AVF_EXPORT NSString *const AVAudioSessionPortLineOut NS_AVAILABLE_IOS(6_0); /* Line level output on a dock connector */ 11 | // AVF_EXPORT NSString *const AVAudioSessionPortHeadphones NS_AVAILABLE_IOS(6_0); /* Headphone or headset output */ 12 | // AVF_EXPORT NSString *const AVAudioSessionPortBluetoothA2DP NS_AVAILABLE_IOS(6_0); /* Output on a Bluetooth A2DP device */ 13 | // AVF_EXPORT NSString *const AVAudioSessionPortBuiltInReceiver NS_AVAILABLE_IOS(6_0); /* The speaker you hold to your ear when on a phone call */ 14 | // AVF_EXPORT NSString *const AVAudioSessionPortBuiltInSpeaker NS_AVAILABLE_IOS(6_0); /* Built-in speaker on an iOS device */ 15 | // AVF_EXPORT NSString *const AVAudioSessionPortHDMI NS_AVAILABLE_IOS(6_0); /* Output via High-Definition Multimedia Interface */ 16 | // AVF_EXPORT NSString *const AVAudioSessionPortAirPlay NS_AVAILABLE_IOS(6_0); /* Output on a remote Air Play device */ 17 | // AVF_EXPORT NSString *const AVAudioSessionPortBluetoothLE NS_AVAILABLE_IOS(7_0); /* Output on a Bluetooth Low Energy device */ 18 | // 19 | // /* port types that refer to either input or output */ 20 | // AVF_EXPORT NSString *const AVAudioSessionPortBluetoothHFP NS_AVAILABLE_IOS(6_0); /* Input or output on a Bluetooth Hands-Free Profile device */ 21 | // AVF_EXPORT NSString *const AVAudioSessionPortUSBAudio NS_AVAILABLE_IOS(6_0); /* Input or output on a Universal Serial Bus device */ 22 | // AVF_EXPORT NSString *const AVAudioSessionPortCarAudio NS_AVAILABLE_IOS(7_0); /* Input or output via Car Audio */ 23 | 24 | 25 | @implementation AVAudioSession (RouteUtils) 26 | 27 | - (BOOL)usingBlueTooth { 28 | NSArray *inputs = self.currentRoute.inputs; 29 | NSArray *blueToothInputRoutes = @[AVAudioSessionPortBluetoothHFP]; 30 | for (AVAudioSessionPortDescription *description in inputs) { 31 | if ([blueToothInputRoutes containsObject:description.portType]) { 32 | return YES; 33 | } 34 | } 35 | 36 | NSArray *outputs = self.currentRoute.outputs; 37 | NSArray *blueToothOutputRoutes = @[AVAudioSessionPortBluetoothHFP, AVAudioSessionPortBluetoothA2DP, AVAudioSessionPortBluetoothLE]; 38 | for (AVAudioSessionPortDescription *description in outputs) { 39 | if ([blueToothOutputRoutes containsObject:description.portType]) { 40 | return YES; 41 | } 42 | } 43 | 44 | return NO; 45 | } 46 | 47 | - (BOOL)usingWiredMicrophone { 48 | NSArray *inputs = self.currentRoute.inputs; 49 | NSArray *headSetInputRoutes = @[AVAudioSessionPortHeadsetMic]; 50 | for (AVAudioSessionPortDescription *description in inputs) { 51 | if ([headSetInputRoutes containsObject:description.portType]) { 52 | return YES; 53 | } 54 | } 55 | 56 | NSArray *outputs = self.currentRoute.outputs; 57 | NSArray *headSetOutputRoutes = @[AVAudioSessionPortHeadphones, AVAudioSessionPortUSBAudio]; 58 | for (AVAudioSessionPortDescription *description in outputs) { 59 | if ([headSetOutputRoutes containsObject:description.portType]) { 60 | return YES; 61 | } 62 | } 63 | return NO; 64 | } 65 | 66 | - (BOOL)shouldShowEarphoneAlert 67 | { 68 | // 用户如果没有带耳机,则应该提出提示,目前采用保守策略,即尽量减少alert弹出,所以,我们认为只要不是用手机内置的听筒或者喇叭作为声音外放的,都认为用户带了耳机 69 | NSArray *outputs = self.currentRoute.outputs; 70 | NSArray *headSetOutputRoutes = @[AVAudioSessionPortBuiltInReceiver, AVAudioSessionPortBuiltInSpeaker]; 71 | for (AVAudioSessionPortDescription *description in outputs) { 72 | if ([headSetOutputRoutes containsObject:description.portType]) { 73 | return YES; 74 | } 75 | } 76 | return NO; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /AUPlayer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AUPlayer 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. 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 | -------------------------------------------------------------------------------- /AUPlayer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AUPlayer 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 20 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]]; 21 | self.window.rootViewController = navigationController; 22 | [self.window makeKeyAndVisible]; 23 | return YES; 24 | } 25 | 26 | - (void)applicationWillResignActive:(UIApplication *)application { 27 | // 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. 28 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 29 | } 30 | 31 | 32 | - (void)applicationDidEnterBackground:(UIApplication *)application { 33 | // 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. 34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 35 | } 36 | 37 | 38 | - (void)applicationWillEnterForeground:(UIApplication *)application { 39 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 40 | } 41 | 42 | 43 | - (void)applicationDidBecomeActive:(UIApplication *)application { 44 | // 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. 45 | } 46 | 47 | 48 | - (void)applicationWillTerminate:(UIApplication *)application { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /AUPlayer/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /AUPlayer/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 | -------------------------------------------------------------------------------- /AUPlayer/ELAudioSession.h: -------------------------------------------------------------------------------- 1 | // 2 | // ELAudioSession.h 3 | // video_player 4 | // 5 | // Created by apple on 16/9/5. 6 | // Copyright © 2016年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | extern const NSTimeInterval AUSAudioSessionLatency_Background; 13 | extern const NSTimeInterval AUSAudioSessionLatency_Default; 14 | extern const NSTimeInterval AUSAudioSessionLatency_LowLatency; 15 | 16 | @interface ELAudioSession : NSObject 17 | 18 | + (ELAudioSession *)sharedInstance; 19 | 20 | @property(nonatomic, strong) AVAudioSession *audioSession; // Underlying system audio session 21 | @property(nonatomic, assign) Float64 preferredSampleRate; 22 | @property(nonatomic, assign, readonly) Float64 currentSampleRate; 23 | @property(nonatomic, assign) NSTimeInterval preferredLatency; 24 | @property(nonatomic, assign) BOOL active; 25 | @property(nonatomic, strong) NSString *category; 26 | 27 | - (void)addRouteChangeListener; 28 | @end 29 | -------------------------------------------------------------------------------- /AUPlayer/ELAudioSession.m: -------------------------------------------------------------------------------- 1 | // 2 | // ELAudioSession.m 3 | // video_player 4 | // 5 | // Created by apple on 16/9/5. 6 | // Copyright © 2016年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import "ELAudioSession.h" 10 | #import "AVAudioSession+RouteUtils.h" 11 | 12 | const NSTimeInterval AUSAudioSessionLatency_Background = 0.0929; 13 | const NSTimeInterval AUSAudioSessionLatency_Default = 0.0232; 14 | const NSTimeInterval AUSAudioSessionLatency_LowLatency = 0.0058; 15 | 16 | @implementation ELAudioSession 17 | 18 | + (ELAudioSession *)sharedInstance 19 | { 20 | static ELAudioSession *instance = NULL; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | instance = [[ELAudioSession alloc] init]; 24 | }); 25 | return instance; 26 | } 27 | 28 | - (id)init 29 | { 30 | if((self = [super init])) 31 | { 32 | _preferredSampleRate = _currentSampleRate = 44100.0; 33 | _audioSession = [AVAudioSession sharedInstance]; 34 | } 35 | return self; 36 | } 37 | 38 | - (void)setCategory:(NSString *)category 39 | { 40 | _category = category; 41 | 42 | NSError *error = nil; 43 | if(![self.audioSession setCategory:_category error:&error]) 44 | NSLog(@"Could note set category on audio session: %@", error.localizedDescription); 45 | } 46 | 47 | - (void)setActive:(BOOL)active 48 | { 49 | _active = active; 50 | 51 | NSError *error = nil; 52 | 53 | if(![self.audioSession setPreferredSampleRate:self.preferredSampleRate error:&error]) 54 | NSLog(@"Error when setting sample rate on audio session: %@", error.localizedDescription); 55 | 56 | if(![self.audioSession setActive:_active error:&error]) 57 | NSLog(@"Error when setting active state of audio session: %@", error.localizedDescription); 58 | 59 | _currentSampleRate = [self.audioSession sampleRate]; 60 | } 61 | 62 | - (void)setPreferredLatency:(NSTimeInterval)preferredLatency 63 | { 64 | _preferredLatency = preferredLatency; 65 | 66 | NSError *error = nil; 67 | if(![self.audioSession setPreferredIOBufferDuration:_preferredLatency error:&error]) 68 | NSLog(@"Error when setting preferred I/O buffer duration"); 69 | } 70 | 71 | - (void)addRouteChangeListener 72 | { 73 | [[NSNotificationCenter defaultCenter] addObserver:self 74 | selector:@selector(onNotificationAudioRouteChange:) 75 | name:AVAudioSessionRouteChangeNotification 76 | object:nil]; 77 | [self adjustOnRouteChange]; 78 | } 79 | 80 | #pragma mark - notification observer 81 | 82 | - (void)onNotificationAudioRouteChange:(NSNotification *)sender { 83 | [self adjustOnRouteChange]; 84 | } 85 | 86 | - (void)adjustOnRouteChange 87 | { 88 | AVAudioSessionRouteDescription *currentRoute = [[AVAudioSession sharedInstance] currentRoute]; 89 | if (currentRoute) { 90 | if ([[AVAudioSession sharedInstance] usingWiredMicrophone]) { 91 | } else { 92 | if (![[AVAudioSession sharedInstance] usingBlueTooth]) { 93 | [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil]; 94 | } 95 | } 96 | } 97 | } 98 | @end 99 | -------------------------------------------------------------------------------- /AUPlayer/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /AUPlayer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // AUPlayer 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /AUPlayer/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // AUPlayer 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "CommonUtil.h" 11 | #import "AUGraphPlayer.h" 12 | 13 | @interface ViewController () 14 | @property(nonatomic, assign) BOOL isAcc; 15 | @end 16 | 17 | @implementation ViewController 18 | { 19 | AUGraphPlayer* graphPlayer; 20 | } 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | // Do any additional setup after loading the view, typically from a nib. 24 | _isAcc = NO; 25 | } 26 | 27 | - (IBAction)playMusic:(id)sender { 28 | NSLog(@"Play Music..."); 29 | if(graphPlayer) { 30 | [graphPlayer stop]; 31 | } 32 | // NSString* filePath = [CommonUtil bundlePath:@"MiAmor.mp3"]; 33 | NSString* filePath = [CommonUtil bundlePath:@"0fe2a7e9c51012210eaaa1e2b103b1b1.m4a"]; 34 | graphPlayer = [[AUGraphPlayer alloc] initWithFilePath:filePath]; 35 | [graphPlayer play]; 36 | } 37 | - (IBAction)switch:(id)sender { 38 | _isAcc = !_isAcc; 39 | [graphPlayer setInputSource:_isAcc]; 40 | } 41 | - (IBAction)stopMusic:(id)sender { 42 | NSLog(@"Stop Music..."); 43 | [graphPlayer stop]; 44 | } 45 | 46 | - (void)didReceiveMemoryWarning { 47 | [super didReceiveMemoryWarning]; 48 | // Dispose of any resources that can be recreated. 49 | } 50 | 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /AUPlayer/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 31 | 38 | 47 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /AUPlayer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AUPlayer 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. 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 | -------------------------------------------------------------------------------- /AUPlayer/resource/0fe2a7e9c51012210eaaa1e2b103b1b1.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanxiaokai/iOS-AUPlayer/14045632da87aa4de5da1e43fa403ce6289c7480/AUPlayer/resource/0fe2a7e9c51012210eaaa1e2b103b1b1.m4a -------------------------------------------------------------------------------- /AUPlayer/resource/MiAmor.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanxiaokai/iOS-AUPlayer/14045632da87aa4de5da1e43fa403ce6289c7480/AUPlayer/resource/MiAmor.mp3 -------------------------------------------------------------------------------- /AUPlayer/utils/CommonUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommonUtil.h 3 | // video_player 4 | // 5 | // Created by apple on 16/8/25. 6 | // Copyright © 2016年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CommonUtil : NSObject 12 | 13 | +(NSString *)bundlePath:(NSString *)fileName; 14 | 15 | +(NSString *)documentsPath:(NSString *)fileName; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /AUPlayer/utils/CommonUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // CommonUtil.m 3 | // video_player 4 | // 5 | // Created by apple on 16/8/25. 6 | // Copyright © 2016年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import "CommonUtil.h" 10 | 11 | @implementation CommonUtil 12 | 13 | +(NSString *)bundlePath:(NSString *)fileName { 14 | return [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:fileName]; 15 | } 16 | 17 | +(NSString *)documentsPath:(NSString *)fileName { 18 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 19 | NSString *documentsDirectory = [paths objectAtIndex:0]; 20 | return [documentsDirectory stringByAppendingPathComponent:fileName]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AUPlayerTests/AUPlayerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AUPlayerTests.m 3 | // AUPlayerTests 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AUPlayerTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AUPlayerTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /AUPlayerTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /AUPlayerUITests/AUPlayerUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AUPlayerUITests.m 3 | // AUPlayerUITests 4 | // 5 | // Created by apple on 2017/2/9. 6 | // Copyright © 2017年 xiaokai.zhan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AUPlayerUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AUPlayerUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /AUPlayerUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | --------------------------------------------------------------------------------