├── ACBAVPlayerExtension
├── Screenshots
│ ├── AVPlayerGif1.gif
│ └── AVPlayerScreen1.png
├── Classes
│ ├── ViewControllers
│ │ ├── ViewController.h
│ │ └── ViewController.m
│ ├── General
│ │ ├── AppDelegate.h
│ │ └── AppDelegate.m
│ └── AudioProcessing
│ │ ├── ACBAudioProcessHelper.h
│ │ ├── AVPlayer+ACBHelper.h
│ │ ├── MYAudioTapProcessor.h
│ │ ├── AVPlayer+ACBHelper.m
│ │ ├── ACBAudioProcessHelper.m
│ │ └── MYAudioTapProcessor.m
├── main.m
├── Info.plist
└── Resources
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ └── Assets.xcassets
│ └── AppIcon.appiconset
│ └── Contents.json
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── ACBAVPlayerExtension.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcshareddata
│ └── xcschemes
│ │ └── ACBAVPlayer.xcscheme
└── project.pbxproj
├── ACBAVPlayer
├── ACBAVPlayer.h
└── Info.plist
├── .gitignore
├── Package.swift
├── ACBAVPlayerTests
├── Info.plist
└── ACBAVPlayerTests.swift
├── ACBAVPlayer.podspec
├── LICENSE
└── README.md
/ACBAVPlayerExtension/Screenshots/AVPlayerGif1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akhilcb/ACBAVPlayerExtension/HEAD/ACBAVPlayerExtension/Screenshots/AVPlayerGif1.gif
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Screenshots/AVPlayerScreen1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akhilcb/ACBAVPlayerExtension/HEAD/ACBAVPlayerExtension/Screenshots/AVPlayerScreen1.png
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/ViewControllers/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // ACBAVPlayerExtension
4 | //
5 | // Created by Akhil on 8/10/17.
6 | // Copyright © 2017 akhil. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/General/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ACBAVPlayerExtension
4 | //
5 | // Created by Akhil on 8/10/17.
6 | // Copyright © 2017 akhil. 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 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ACBAVPlayerExtension
4 | //
5 | // Created by Akhil on 8/10/17.
6 | // Copyright © 2017 akhil. 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 |
--------------------------------------------------------------------------------
/ACBAVPlayer/ACBAVPlayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // ACBAVPlayer.h
3 | // ACBAVPlayer
4 | //
5 | // Created by Akhil C Balan on 1/7/18.
6 | // Copyright © 2018 akhil. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for ACBAVPlayer.
12 | FOUNDATION_EXPORT double ACBAVPlayerVersionNumber;
13 |
14 | //! Project version string for ACBAVPlayer.
15 | FOUNDATION_EXPORT const unsigned char ACBAVPlayerVersionString[];
16 |
17 |
18 | #import
19 |
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 |
3 | ## Build generated
4 | build/
5 | DerivedData/
6 |
7 | ## Various settings
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata/
17 |
18 | ## Other
19 | *.moved-aside
20 | *.xccheckout
21 | *.xcscmblueprint
22 |
23 | ## Obj-C/Swift specific
24 | *.hmap
25 | *.ipa
26 | *.dSYM.zip
27 | *.dSYM
28 |
29 | ## CocoaPods
30 | Pods/
31 |
32 | ## Carthage
33 | Carthage/Checkouts
34 | Carthage/Build
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.6
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "ACBAVPlayerExtension",
8 | platforms: [
9 | .iOS(.v14),
10 | .macOS(.v10_12)
11 | ],
12 | products: [
13 | .library(
14 | name: "ACBAVPlayerExtension",
15 | targets: ["ACBAVPlayerExtension"])
16 | ],
17 | dependencies: [
18 | ],
19 | targets: [
20 | .target(
21 | name: "ACBAVPlayerExtension",
22 | dependencies: [],
23 | path: "ACBAVPlayerExtension/Classes/AudioProcessing",
24 | publicHeadersPath: ".")
25 | ],
26 | swiftLanguageVersions: [.v5]
27 | )
28 |
--------------------------------------------------------------------------------
/ACBAVPlayerTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 |
--------------------------------------------------------------------------------
/ACBAVPlayer/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 2.1
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ACBAVPlayer.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "ACBAVPlayer"
3 | s.version = "2.1"
4 | s.summary = "An extension on AVPlayer which converts it to have all useful features of AVAudioPlayer but with streaming support."
5 | s.description = <<-DESC
6 | An extension on AVPlayer which converts it to have all useful features of AVAudioPlayer but with streaming support. Also added additional methods to support Audio visualization from AVPlayer streaming. This extension adds some missing features to AVPlayer.
7 | DESC
8 | s.homepage = "https://github.com/akhilcb/ACBAVPlayerExtension"
9 | s.license = "MIT"
10 | s.author = "Akhil"
11 | s.platform = :ios
12 | s.source = { :git => "https://github.com/akhilcb/ACBAVPlayerExtension.git", :tag => "2.1" }
13 | s.source_files = "ACBAVPlayerExtension", "ACBAVPlayerExtension/Classes/AudioProcessing/*.{h,m}"
14 | s.exclude_files = "ACBAVPlayerExtension/main.m"
15 | s.public_header_files = "ACBAVPlayerExtension/Classes/AudioProcessing/AVPlayer+ACBHelper.h"
16 | end
17 |
--------------------------------------------------------------------------------
/ACBAVPlayerTests/ACBAVPlayerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ACBAVPlayerTests.swift
3 | // ACBAVPlayerTests
4 | //
5 | // Created by Akhil C Balan on 1/7/18.
6 | // Copyright © 2018 akhil. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import ACBAVPlayer
11 |
12 | class ACBAVPlayerTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017, Akhil C Balan(https://github.com/akhilcb)
4 |
5 | All rights reserved
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/AudioProcessing/ACBAudioProcessHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // ACBAudioProcessHelper.h
3 | // ACBAudioPlayer
4 | //
5 | // Created by Akhil C Balan on 3/3/16.
6 | // Copyright © 2016 Akhil. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | typedef void (^ACBAudioProcessHelperMeteringBlock) (NSArray *iAvgPowerList, BOOL iSuccess);
13 | typedef void (^ACBAudioProcessHelperBufferFetchedBlock) (AVAudioPCMBuffer *audioPCMBuffer, BOOL iSuccess);
14 |
15 | @interface ACBAudioProcessHelper : NSObject
16 |
17 | @property (nonatomic, readonly, assign) int numberOfChannels;
18 | @property (nonatomic, weak) AVPlayer *player;
19 | @property (nonatomic, getter=isMeteringEnabled) BOOL meteringEnabled; /* turns level metering on or off. default is off. */
20 |
21 | - (float)averagePowerInLinearFormForChannel:(NSUInteger)channelNumber; //returns in average power in linear form. Value is in between 0 to 1.
22 | - (float)averagePowerForChannel:(NSUInteger)channelNumber; /* returns average power in decibels for a given channel */
23 |
24 | - (void)averagePowerListWithCallbackBlock:(ACBAudioProcessHelperMeteringBlock)iMeteringCallbackBlock;
25 | - (void)averagePowerListInLinearFormWithCallbackBlock:(ACBAudioProcessHelperMeteringBlock)iMeteringCallbackBlock;
26 | - (void)audioPCMBufferFetchedWithCallbackBlock:(ACBAudioProcessHelperBufferFetchedBlock)iAudioBufferFetchedBlock;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/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 | 2.1
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSAppTransportSecurity
24 |
25 | NSAllowsArbitraryLoads
26 |
27 |
28 | UILaunchStoryboardName
29 | LaunchScreen
30 | UIMainStoryboardFile
31 | Main
32 | UIRequiredDeviceCapabilities
33 |
34 | armv7
35 |
36 | UIRequiresFullScreen
37 |
38 | UISupportedInterfaceOrientations
39 |
40 | UIInterfaceOrientationPortrait
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UISupportedInterfaceOrientations~ipad
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationPortraitUpsideDown
48 | UIInterfaceOrientationLandscapeLeft
49 | UIInterfaceOrientationLandscapeRight
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Resources/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 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/AudioProcessing/AVPlayer+ACBHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // AVPlayer+ACBHelper.h
3 | // ACBAudioPlayer
4 | //
5 | // Created by Akhil C Balan on 3/3/16.
6 | // Copyright © 2016 Akhil. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | typedef void (^ACBAVPlayerMeteringBlock) (NSArray * _Nullable iAvgPowerList, BOOL iSuccess);
13 | typedef void (^ACBAVPlayerBufferFetchedBlock) (AVAudioPCMBuffer * _Nullable audioPCMBuffer, BOOL iSuccess);
14 |
15 |
16 | @interface AVPlayer(ACBHelper)
17 |
18 | @property (nonatomic, readonly, assign) int numberOfChannels;
19 |
20 | //stop video
21 | - (void)stop;
22 |
23 |
24 | /* metering */
25 | @property (nonatomic, getter=isMeteringEnabled) BOOL meteringEnabled; /* turns level metering on or off. default is off. */
26 |
27 | - (void)updateMeters; /* call to refresh meter values */ //does nothing for now
28 |
29 | - (float)peakPowerForChannel:(NSUInteger)channelNumber; /* for peak power in decibels for a given channel. returns average power for now */
30 | - (float)averagePowerForChannel:(NSUInteger)channelNumber; /* returns average power in decibels for a given channel */
31 |
32 |
33 | //use this to repeatedly fetch average power list(in decibels) for all channels in iMeteringCallbackBlock. This block will be executed each time a value is fetched. Index of array is channel number
34 | - (void)averagePowerListWithCallbackBlock:(ACBAVPlayerMeteringBlock _Nullable )iMeteringCallbackBlock;
35 |
36 | - (float)averagePowerInLinearFormForChannel:(NSUInteger)channelNumber; //returns in average power in linear form. Value is in between 0 to 1.
37 |
38 | //fetch average power list in linear form(values in between 0 and 1)
39 | - (void)averagePowerListInLinearFormWithCallbackBlock:(ACBAVPlayerMeteringBlock _Nullable )iMeteringCallbackBlock;
40 |
41 | //fetch AVAudioPCMBuffer. it has useful methods to manipuate buffers or to display a visualizer
42 | - (void)audioPCMBufferFetchedWithCallbackBlock:(ACBAVPlayerBufferFetchedBlock _Nullable )iAudioBufferFetchedBlock;
43 |
44 | //use this instead of "replaceCurrentItemWithPlayerItem" for metering to work.
45 | - (void)replaceCurrentItemAndUpdateMeteringForPlayerItem:(nullable AVPlayerItem *)item;
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/General/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ACBAVPlayerExtension
4 | //
5 | // Created by Akhil on 8/10/17.
6 | // Copyright © 2017 akhil. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // 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.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // 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.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // 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.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // 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.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension.xcodeproj/xcshareddata/xcschemes/ACBAVPlayer.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
52 |
53 |
59 |
60 |
66 |
67 |
68 |
69 |
71 |
72 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/AudioProcessing/MYAudioTapProcessor.h:
--------------------------------------------------------------------------------
1 | /*
2 | File: MYAudioTapProcessor.h
3 | Abstract: Audio tap processor using MTAudioProcessingTap for audio visualization and processing.
4 | Version: 1.0.1
5 |
6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 | Inc. ("Apple") in consideration of your agreement to the following
8 | terms, and your use, installation, modification or redistribution of
9 | this Apple software constitutes acceptance of these terms. If you do
10 | not agree with these terms, please do not use, install, modify or
11 | redistribute this Apple software.
12 |
13 | In consideration of your agreement to abide by the following terms, and
14 | subject to these terms, Apple grants you a personal, non-exclusive
15 | license, under Apple's copyrights in this original Apple software (the
16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 | Software, with or without modifications, in source and/or binary forms;
18 | provided that if you redistribute the Apple Software in its entirety and
19 | without modifications, you must retain this notice and the following
20 | text and disclaimers in all such redistributions of the Apple Software.
21 | Neither the name, trademarks, service marks or logos of Apple Inc. may
22 | be used to endorse or promote products derived from the Apple Software
23 | without specific prior written permission from Apple. Except as
24 | expressly stated in this notice, no other rights or licenses, express or
25 | implied, are granted by Apple herein, including but not limited to any
26 | patent rights that may be infringed by your derivative works or by other
27 | works in which the Apple Software may be incorporated.
28 |
29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 |
35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 | POSSIBILITY OF SUCH DAMAGE.
43 |
44 | Copyright (C) 2013 Apple Inc. All Rights Reserved.
45 |
46 | Modified to add additional methods
47 | */
48 |
49 | #import
50 |
51 | @class AVAudioMix;
52 | @class AVAssetTrack;
53 | @class AVAudioPCMBuffer;
54 |
55 | @protocol MYAudioTabProcessorDelegate;
56 |
57 | @interface MYAudioTapProcessor : NSObject
58 |
59 | // Designated initializer.
60 | - (id)initWithAudioAssetTrack:(AVAssetTrack *)audioAssetTrack;
61 |
62 | // Properties
63 | @property (readonly, nonatomic) AVAssetTrack *audioAssetTrack;
64 | @property (readonly, nonatomic) AVAudioMix *audioMix;
65 | @property (weak, nonatomic) id delegate;
66 | @property (nonatomic, getter = isBandpassFilterEnabled) BOOL enableBandpassFilter;
67 | @property (nonatomic) float centerFrequency; // [0 .. 1]
68 | @property (nonatomic) float bandwidth; // [0 .. 1]
69 | @property (nonatomic, assign) int numberOfChannels;
70 |
71 | - (void)stopProcessing;
72 |
73 | @end
74 |
75 | #pragma mark - Protocols
76 |
77 | @protocol MYAudioTabProcessorDelegate
78 |
79 | // Add comment…
80 | - (void)audioTabProcessor:(MYAudioTapProcessor *)audioTabProcessor hasNewLeftChannelValue:(float)leftChannelValue rightChannelValue:(float)rightChannelValue;
81 | - (void)audioTabProcessor:(MYAudioTapProcessor *)audioTabProcessor hasNewChannelVolumeList:(NSArray *)iChannelVolumeList;
82 | - (void)audioTabProcessor:(MYAudioTapProcessor *)audioTabProcessor didReceiveBuffer:(AVAudioPCMBuffer *)buffer;
83 |
84 | @end
85 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/ViewControllers/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // ACBAVPlayerExtension
4 | //
5 | // Created by Akhil on 8/10/17.
6 | // Copyright © 2017 akhil. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "AVPlayer+ACBHelper.h"
11 | #import
12 |
13 |
14 | @interface ViewController ()
15 |
16 | @property (nonatomic, strong) AVPlayer *player;
17 | @property (nonatomic, weak) IBOutlet UIProgressView *progressBar;
18 | @property (nonatomic, strong) NSString *url;
19 | @property (nonatomic, strong) NSString *firstUrl;
20 | @property (nonatomic, strong) NSString *secondUrl;
21 |
22 | @end
23 |
24 |
25 | @implementation ViewController
26 |
27 | - (void)viewDidLoad {
28 | [super viewDidLoad];
29 | self.progressBar.progress = 0.0;
30 | self.firstUrl = @"https://archive.org/download/WildlifeSampleVideo/Wildlife.mp4";
31 | // @"http://content.viki.com/test_ios/ios_240.m3u8";
32 | //@"https://scontent.cdninstagram.com/hphotos-xfa1/t50.2886-16/11719145_918467924880620_816495633_n.mp4";
33 | //http://techslides.com/demos/sample-videos/small.mp4
34 | self.secondUrl = @"https://files.inqscribe.com/samples/IS_Intro.mp4";
35 |
36 | self.url = self.firstUrl;
37 | [self setupPlayer];
38 | }
39 |
40 |
41 | - (void)itemDidFinishPlaying:(NSNotification *)notification {
42 | [self.player pause];
43 | [self.player seekToTime:kCMTimeZero];
44 | }
45 |
46 |
47 | - (void)setupPlayer {
48 | NSURL *audioURL = [NSURL URLWithString:self.url];
49 |
50 | if (self.player) {
51 | [self.player stop];
52 | [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
53 | self.player = nil;
54 | }
55 |
56 | self.player = [[AVPlayer alloc] initWithURL:audioURL];
57 | self.player.meteringEnabled = true;
58 |
59 | // Subscribe to the AVPlayerItem's DidPlayToEndTime notification.
60 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
61 |
62 |
63 | [self.player averagePowerListInLinearFormWithCallbackBlock:^(NSArray *iAvgPowerList, BOOL iSuccess) {
64 | if (iAvgPowerList.count > 0) {
65 | double power = [iAvgPowerList[0] doubleValue];
66 | if (iAvgPowerList.count > 1) {
67 | double secondPower = [iAvgPowerList[1] doubleValue];
68 | power = (power + secondPower) / 2;
69 | }
70 |
71 | dispatch_async(dispatch_get_main_queue(), ^{
72 | [self.progressBar setProgress:(power * 10)];
73 | });
74 |
75 | }
76 | }];
77 |
78 | //*********************************
79 | //Similar to an AVAudioPlayer, you can use different methods on AVPlayer while streaming such as:
80 | //Checkout AVPlayer+ACBHelper.h for details
81 | // [self.player averagePowerForChannel:0];
82 | // [self.player averagePowerInLinearFormForChannel:0];
83 | // [self.player peakPowerForChannel:0];
84 | //Additional method which fetches AVAudioPCMBuffer for the stream
85 | // [self.player audioPCMBufferFetchedWithCallbackBlock:^(AVAudioPCMBuffer *audioPCMBuffer, BOOL iSuccess) {
86 | // }];
87 | //*********************************
88 | }
89 |
90 |
91 | - (IBAction)playTapped:(id)sender {
92 | [self.player play];
93 | }
94 |
95 |
96 | - (IBAction)stopTapped:(id)sender {
97 | [self.player stop];
98 | [self setupPlayer];
99 | [self.progressBar performSelector:@selector(setProgress:) withObject:@(0.0) afterDelay:0.2f];
100 | }
101 |
102 |
103 | - (IBAction)pauseTapped:(id)sender {
104 | [self.player pause];
105 | }
106 |
107 |
108 | - (IBAction)segmentTapped:(id)sender {
109 | UISegmentedControl *segment = (UISegmentedControl *)sender;
110 |
111 | if (segment.selectedSegmentIndex == 0 && self.url != self.firstUrl) {
112 | self.url = self.firstUrl;
113 | [self setupPlayer];
114 | [self.progressBar performSelector:@selector(setProgress:) withObject:@(0.0) afterDelay:0.2f];
115 | } else if (segment.selectedSegmentIndex == 1 && self.url != self.secondUrl) {
116 | self.url = self.secondUrl;
117 | [self setupPlayer];
118 | [self.progressBar performSelector:@selector(setProgress:) withObject:@(0.0) afterDelay:0.2f];
119 | }
120 | }
121 |
122 |
123 | @end
124 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ACBAVPlayerExtension
2 |
3 | [](https://img.shields.io/cocoapods/v/ACBAVPlayer.svg)
4 | [](https://github.com/Carthage/Carthage)
5 | [](https://github.com/akhilcb/ACBAVPlayerExtension)
6 | [](http://cocoapods.org/pods/ACBAVPlayer)
7 |
8 | An extension on `AVPlayer` which converts it to have all useful features of `AVAudioPlayer` but with streaming support. Also added additional methods to support Audio visualization from `AVPlayer` streaming. This extension adds some missing features to `AVPlayer`.
9 |
10 | This projects shows a simple example on how to use it. ViewController has a `UIProgressView` which displays `averagePower` as a volume meter while streaming an audio through `AVPlayer`. This is very similar to how we would normally use `AVAudioPlayer`, but with some additional methods which makes it easy to display the `averagePower`. `audioPCMBufferFetchedWithCallbackBlock` can be used to fetch `AVAudioPCMBuffer` which can be used for Audio Visualization. Added `stop` method to stop player.
11 |
12 |
13 | ## Demo
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | ## Setup
25 |
26 | Carthage or Cocoapods can be used to integrate this to a project.
27 |
28 | ### Carthage
29 |
30 | ```
31 | github "akhilcb/ACBAVPlayerExtension" ~> 2.1
32 |
33 | ```
34 |
35 | ### Cocoapods
36 |
37 | ```
38 | pod 'ACBAVPlayer'
39 |
40 | ```
41 |
42 | ## AVPlayer Extension Interface
43 |
44 | ```
45 | @property (nonatomic, readonly, assign) int numberOfChannels;
46 | //stop video
47 | - (void)stop;
48 |
49 | /* metering */
50 | @property (nonatomic, getter=isMeteringEnabled) BOOL meteringEnabled; /* turns level metering on or off. default is off. */
51 |
52 | - (void)updateMeters; /* call to refresh meter values */
53 | - (float)peakPowerForChannel:(NSUInteger)channelNumber; /* for peak power in decibels for a given channel. returns average power for now */
54 | - (float)averagePowerForChannel:(NSUInteger)channelNumber; /* returns average power in decibels for a given channel */
55 | //use this to repeatedly fetch average power list(in decibels) for all channels in iMeteringCallbackBlock. This block will be executed each time a value is fetched. Index of array is channel number
56 | - (void)averagePowerListWithCallbackBlock:(ACBAVPlayerMeteringBlock)iMeteringCallbackBlock;
57 | - (float)averagePowerInLinearFormForChannel:(NSUInteger)channelNumber; //returns in average power in linear form. Value is in between 0 to 1.
58 | //fetch average power list in linear form(values in between 0 and 1)
59 | - (void)averagePowerListInLinearFormWithCallbackBlock:(ACBAVPlayerMeteringBlock)iMeteringCallbackBlock;
60 | //fetch AVAudioPCMBuffer. it has useful methods to manipuate buffers or to display a visualizer
61 | - (void)audioPCMBufferFetchedWithCallbackBlock:(ACBAVPlayerBufferFetchedBlock)iAudioBufferFetchedBlock;
62 | - (void)replaceCurrentItemAndUpdateMeteringForPlayerItem:(AVPlayerItem *)item; //use this instead of "replaceCurrentItemWithPlayerItem" for metering to work.
63 | ```
64 |
65 | ___Note: This is a beta version. There could be some issues(Hopefully minor). Use at your own risk.___
66 |
67 |
68 | ## Usage
69 |
70 | ```
71 | self.player = [[AVPlayer alloc] initWithURL:remoteURL];
72 | self.player.meteringEnabled = true;
73 |
74 | [self.player averagePowerListInLinearFormWithCallbackBlock:^(NSArray *iAvgPowerList, BOOL iSuccess) {
75 | if (iAvgPowerList.count > 0) {
76 | double power = [iAvgPowerList[0] doubleValue];
77 | if (iAvgPowerList.count > 1) {
78 | double secondPower = [iAvgPowerList[1] doubleValue];
79 | power = (power + secondPower) / 2;
80 | }
81 | dispatch_async(dispatch_get_main_queue(), ^{
82 | [self.progressBar setProgress:(power * 10)];
83 | });
84 | }
85 | }];
86 | ```
87 |
88 | ## Screenshots
89 |
90 |
91 |
92 |
93 |
94 |
95 | ## License
96 |
97 | MIT License
98 |
99 | Copyright (c) 2017, Akhil C Balan(https://github.com/akhilcb)
100 |
101 | All rights reserved.
102 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/AudioProcessing/AVPlayer+ACBHelper.m:
--------------------------------------------------------------------------------
1 | //
2 | // AVPlayer+ACBHelper.m
3 | // ACBAudioPlayer
4 | //
5 | // Created by Akhil C Balan on 3/3/16.
6 | // Copyright © 2016 Akhil. All rights reserved.
7 | //
8 |
9 | #import "AVPlayer+ACBHelper.h"
10 | #import "ACBAudioProcessHelper.h"
11 | #import
12 |
13 |
14 | NSString const *ACBAVPlayerAudioProcessHelperkey = @"ACBAVPlayerAudioProcessHelperkey";
15 |
16 | @interface AVPlayer (ACBHelper_Private)
17 |
18 | @property (nonatomic, strong) ACBAudioProcessHelper *audioProcessHelper;
19 |
20 | @end
21 |
22 |
23 | @implementation AVPlayer (ACBHelper_Private)
24 |
25 | - (void)setAudioProcessHelper:(ACBAudioProcessHelper *)iAudioProcessHelper {
26 | objc_setAssociatedObject(self, &ACBAVPlayerAudioProcessHelperkey, iAudioProcessHelper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
27 | }
28 |
29 |
30 | - (ACBAudioProcessHelper *)audioProcessHelper {
31 | return objc_getAssociatedObject(self, &ACBAVPlayerAudioProcessHelperkey);
32 | }
33 |
34 | @end
35 |
36 |
37 | @implementation AVPlayer(ACBHelper)
38 |
39 |
40 | - (void)stop {
41 | [self seekToTime:kCMTimeZero];
42 | [self pause];
43 | [self replaceCurrentItemWithPlayerItem:nil];
44 | }
45 |
46 |
47 | - (ACBAudioProcessHelper *)createAudioProcessHelper {
48 | if (!self.audioProcessHelper) {
49 | self.audioProcessHelper = [[ACBAudioProcessHelper alloc] init];
50 | self.audioProcessHelper.player = self;
51 | }
52 | return self.audioProcessHelper;
53 | }
54 |
55 |
56 | - (int)numberOfChannels {
57 | return self.audioProcessHelper.numberOfChannels;
58 | }
59 |
60 |
61 | - (void)setMeteringEnabled:(BOOL)iMeteringEnabled {
62 |
63 | if (!self.audioProcessHelper) {
64 | [self createAudioProcessHelper];
65 | }
66 |
67 | [self.audioProcessHelper setMeteringEnabled:iMeteringEnabled];
68 | }
69 |
70 |
71 | - (BOOL)isMeteringEnabled {
72 | return self.audioProcessHelper.isMeteringEnabled;
73 | }
74 |
75 |
76 | - (void)replaceCurrentItemAndUpdateMeteringForPlayerItem:(nullable AVPlayerItem *)item {
77 | BOOL prevMetering = self.isMeteringEnabled;
78 | if (prevMetering) {
79 | self.meteringEnabled = false;
80 | }
81 | [self replaceCurrentItemWithPlayerItem:item];
82 | self.meteringEnabled = prevMetering;
83 | }
84 |
85 |
86 | - (float)averagePowerForChannel:(NSUInteger)channelNumber {
87 |
88 | if (!self.audioProcessHelper) {
89 | NSLog(@"Enable Metering before calling this method");
90 | return 0.0f;
91 | }
92 |
93 | return [self.audioProcessHelper averagePowerForChannel:channelNumber];
94 | }
95 |
96 |
97 | - (float)averagePowerInLinearFormForChannel:(NSUInteger)channelNumber {
98 |
99 | if (!self.audioProcessHelper) {
100 | NSLog(@"Enable Metering before calling this method");
101 | return 0.0f;
102 | }
103 |
104 | return [self.audioProcessHelper averagePowerInLinearFormForChannel:channelNumber];
105 | }
106 |
107 |
108 | - (void)averagePowerListWithCallbackBlock:(ACBAVPlayerMeteringBlock)iMeteringCallbackBlock {
109 |
110 | if (!self.audioProcessHelper) {
111 | NSLog(@"Enable Metering before calling this method");
112 | iMeteringCallbackBlock(nil, false);
113 | }
114 |
115 | [self.audioProcessHelper averagePowerListWithCallbackBlock:^(NSArray *iAvgPowerList, BOOL iSuccess) {
116 | iMeteringCallbackBlock(iAvgPowerList, iSuccess);
117 | }];
118 | }
119 |
120 |
121 | - (void)averagePowerListInLinearFormWithCallbackBlock:(ACBAVPlayerMeteringBlock)iMeteringCallbackBlock {
122 |
123 | if (!self.audioProcessHelper) {
124 | NSLog(@"Enable Metering before calling this method");
125 | iMeteringCallbackBlock(nil, false);
126 | }
127 |
128 | [self.audioProcessHelper averagePowerListInLinearFormWithCallbackBlock:^(NSArray *iAvgPowerList, BOOL iSuccess) {
129 | iMeteringCallbackBlock(iAvgPowerList, iSuccess);
130 | }];
131 | }
132 |
133 |
134 | - (void)audioPCMBufferFetchedWithCallbackBlock:(ACBAVPlayerBufferFetchedBlock)iAudioBufferFetchedBlock {
135 |
136 | if (!self.audioProcessHelper) {
137 | NSLog(@"Enable Metering before calling this method");
138 | iAudioBufferFetchedBlock(nil, false);
139 | }
140 |
141 | [self.audioProcessHelper audioPCMBufferFetchedWithCallbackBlock:^(AVAudioPCMBuffer *audioPCMBuffer, BOOL iSuccess) {
142 | iAudioBufferFetchedBlock(audioPCMBuffer, iSuccess);
143 | }];
144 | }
145 |
146 |
147 | - (void)updateMeters {
148 | //do nothing
149 | }
150 |
151 |
152 | - (float)peakPowerForChannel:(NSUInteger)channelNumber {
153 |
154 | return [self averagePowerForChannel:channelNumber];
155 | }
156 |
157 |
158 | @end
159 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/AudioProcessing/ACBAudioProcessHelper.m:
--------------------------------------------------------------------------------
1 | //
2 | // ACBAudioProcessHelper.m
3 | // ACBAudioPlayer
4 | //
5 | // Created by Akhil C Balan on 3/3/16.
6 | // Copyright © 2016 Akhil. All rights reserved.
7 | //
8 |
9 | #import "ACBAudioProcessHelper.h"
10 | #import "MYAudioTapProcessor.h"
11 |
12 |
13 | static void *ACBAVPlayerStatusObserverContext = &ACBAVPlayerStatusObserverContext;
14 |
15 | NSString *const kACBAVPlayerCurrentItemKey = @"currentItem";
16 | NSString *const kACBAVPlayerStatusKey = @"status";
17 |
18 |
19 | @interface ACBAudioProcessHelper ()
20 |
21 | @property (strong, nonatomic) MYAudioTapProcessor *audioTapProcessor;
22 | @property (assign) float averagePower;
23 | @property (strong) NSArray *averagePowerList;
24 | @property (strong) NSArray *averagePowerListInLinearForm;
25 | @property (strong) AVAudioPCMBuffer *audioPCMBuffer;
26 | @property (copy) ACBAudioProcessHelperMeteringBlock meteringBlock;
27 | @property (copy) ACBAudioProcessHelperMeteringBlock meteringBlockInLinearForm;
28 | @property (copy) ACBAudioProcessHelperBufferFetchedBlock audioBufferFetchedBlock;
29 | @property (strong) AVPlayerItem *playerItem;
30 |
31 |
32 | - (void)setupMetering;
33 |
34 | @end
35 |
36 |
37 | @implementation ACBAudioProcessHelper
38 |
39 | - (void)createAudioTapProcessor {
40 |
41 | if (!self.audioTapProcessor) {
42 | AVAssetTrack *firstAudioAssetTrack;
43 | NSArray *audioTracks = [self.player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio];
44 | NSLog(@"audioTracks = %@", audioTracks);
45 |
46 | for (AVAssetTrack *assetTrack in self.player.currentItem.asset.tracks) {
47 | if ([assetTrack.mediaType isEqualToString:AVMediaTypeAudio]) {
48 | firstAudioAssetTrack = assetTrack;
49 | break;
50 | }
51 | }
52 |
53 | if (firstAudioAssetTrack) {
54 | self.audioTapProcessor = [[MYAudioTapProcessor alloc] initWithAudioAssetTrack:firstAudioAssetTrack];
55 | self.audioTapProcessor.delegate = self;
56 | }
57 | }
58 | }
59 |
60 |
61 | - (void)setMeteringEnabled:(BOOL)iMeteringEnabled {
62 |
63 | if (!self.isMeteringEnabled && iMeteringEnabled) {
64 | [self setupMetering];
65 | } else if (self.isMeteringEnabled && !iMeteringEnabled) {
66 | self.player.currentItem.audioMix = nil;
67 | [self releaseAudioTapProcessor];
68 | }
69 |
70 | _meteringEnabled = iMeteringEnabled;
71 | }
72 |
73 | - (void)releaseAudioTapProcessor {
74 |
75 | if (!self.audioTapProcessor) {
76 | return;
77 | }
78 |
79 | [self.audioTapProcessor stopProcessing];
80 | self.audioTapProcessor = nil;
81 | }
82 |
83 | - (void)setupMetering {
84 |
85 | if (!self.player.currentItem) {
86 | //wait for currentItem using observer
87 | [self addCurrentItemObserverForPlayer];
88 | } else {
89 |
90 | [self createAudioTapProcessor];
91 |
92 | if (self.audioTapProcessor) {
93 |
94 | if (self.player.currentItem.status == AVPlayerStatusReadyToPlay) {
95 | [self setupAudioMix];
96 | } else {
97 | [self addStatusObserverForPlayerItem];
98 | }
99 | } else {
100 | NSLog(@"failed to setup processor");
101 | }
102 | }
103 | }
104 |
105 |
106 | - (void)setupAudioMix {
107 | // Add audio mix with audio tap processor to current player item.
108 | AVAudioMix *audioMix = self.audioTapProcessor.audioMix;
109 | if (audioMix) {
110 | // Add audio mix with first audio track.
111 | self.player.currentItem.audioMix = audioMix;
112 | }
113 | }
114 |
115 |
116 | #pragma mark - Add/Remove observers
117 |
118 | - (void)addCurrentItemObserverForPlayer {
119 | [self.player addObserver:self
120 | forKeyPath:kACBAVPlayerCurrentItemKey
121 | options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
122 | context:ACBAVPlayerStatusObserverContext];
123 |
124 | }
125 |
126 |
127 | - (void)addStatusObserverForPlayerItem {
128 | if (self.player.currentItem) {
129 | self.playerItem = self.player.currentItem;
130 | [self.playerItem addObserver:self
131 | forKeyPath:kACBAVPlayerStatusKey
132 | options:NSKeyValueObservingOptionNew
133 | context:ACBAVPlayerStatusObserverContext];
134 | }
135 | }
136 |
137 |
138 | - (void)removeCurrentItemObserverFromPlayer {
139 | [self.player removeObserver:self forKeyPath:kACBAVPlayerCurrentItemKey context:ACBAVPlayerStatusObserverContext];
140 | }
141 |
142 |
143 | - (void)removeStatusObserverFromPlayerItem {
144 |
145 | if (self.playerItem) {
146 | [self.playerItem removeObserver:self forKeyPath:kACBAVPlayerStatusKey context:ACBAVPlayerStatusObserverContext];
147 | self.playerItem = nil;
148 | }
149 | }
150 |
151 |
152 | #pragma mark - Key Value Observing
153 |
154 | - (void)observeValueForKeyPath:(NSString*)path
155 | ofObject:(id)object
156 | change:(NSDictionary*)change
157 | context:(void*)context {
158 |
159 | if (context == ACBAVPlayerStatusObserverContext) {
160 |
161 | if ([path isEqualToString:kACBAVPlayerCurrentItemKey]) {
162 |
163 | AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];
164 |
165 | if (newPlayerItem != (id)[NSNull null]) {
166 | [self setupMetering];
167 | }
168 |
169 | [self removeCurrentItemObserverFromPlayer];
170 | } else {
171 | if (self.playerItem && object == self.playerItem) {
172 |
173 | if ([path isEqualToString:kACBAVPlayerStatusKey]) {
174 |
175 | AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
176 |
177 | if (status == AVPlayerStatusReadyToPlay) {
178 |
179 | [self setupAudioMix];
180 | }
181 |
182 | [self removeStatusObserverFromPlayerItem];
183 | }
184 | }
185 | }
186 | } else {
187 | [super observeValueForKeyPath:path ofObject:object change:change context:context];
188 | }
189 | }
190 |
191 |
192 | - (void)averagePowerListWithCallbackBlock:(ACBAudioProcessHelperMeteringBlock)iMeteringCallbackBlock {
193 | self.meteringBlock = iMeteringCallbackBlock;
194 | }
195 |
196 |
197 | - (void)averagePowerListInLinearFormWithCallbackBlock:(ACBAudioProcessHelperMeteringBlock)iMeteringCallbackBlock {
198 | self.meteringBlockInLinearForm = iMeteringCallbackBlock;
199 | }
200 |
201 |
202 | - (void)audioPCMBufferFetchedWithCallbackBlock:(ACBAudioProcessHelperBufferFetchedBlock)iAudioBufferFetchedBlock {
203 | self.audioBufferFetchedBlock = iAudioBufferFetchedBlock;
204 | }
205 |
206 |
207 | - (int)numberOfChannels {
208 |
209 | if (self.audioTapProcessor) {
210 | if (self.audioTapProcessor.numberOfChannels == -1) {
211 | return 0;
212 | } else {
213 | return self.audioTapProcessor.numberOfChannels;
214 | }
215 | }
216 |
217 | return 1;
218 | }
219 |
220 |
221 | #pragma mark - MYAudioTabProcessorDelegate
222 |
223 | - (void)audioTabProcessor:(MYAudioTapProcessor *)audioTabProcessor hasNewLeftChannelValue:(float)leftChannelValue rightChannelValue:(float)rightChannelValue {
224 | // Update left and right channel volume unit meter.
225 |
226 | self.averagePower = (leftChannelValue + rightChannelValue) / 2.0f;
227 | }
228 |
229 |
230 | - (void)audioTabProcessor:(MYAudioTapProcessor *)audioTabProcessor hasNewChannelVolumeList:(NSArray *)iChannelVolumeList {
231 |
232 | self.averagePowerListInLinearForm = iChannelVolumeList;
233 | self.averagePowerList = [self convertAveragePowerListToDecibelFormat:iChannelVolumeList];
234 |
235 | if (self.meteringBlock) {
236 | self.meteringBlock(self.averagePowerList, true);
237 | }
238 |
239 | if (self.meteringBlockInLinearForm) {
240 | self.meteringBlockInLinearForm(self.averagePowerListInLinearForm, true);
241 | }
242 | }
243 |
244 |
245 | - (void)audioTabProcessor:(MYAudioTapProcessor *)audioTabProcessor didReceiveBuffer:(AVAudioPCMBuffer *)buffer {
246 | self.audioPCMBuffer = buffer;
247 |
248 | if (self.audioBufferFetchedBlock) {
249 | self.audioBufferFetchedBlock(buffer, true);
250 | }
251 | }
252 |
253 |
254 | - (float)averagePowerForChannel:(NSUInteger)channelNumber {
255 |
256 | if (channelNumber < self.averagePowerList.count) {
257 | return [self.averagePowerList[channelNumber] floatValue];
258 | }
259 |
260 | return self.averagePower;
261 | }
262 |
263 |
264 | - (float)averagePowerInLinearFormForChannel:(NSUInteger)channelNumber {
265 |
266 | if (channelNumber < self.averagePowerListInLinearForm.count) {
267 | return [self.averagePowerListInLinearForm[channelNumber] floatValue] * 2.8f; //temp fix for correcting to match with avaudiorecorder level measured
268 | }
269 |
270 | return self.averagePower * 2.8f;
271 | }
272 |
273 |
274 | - (NSArray *)convertAveragePowerListToDecibelFormat:(NSArray *)iChannelVolumeList {
275 |
276 | NSMutableArray *aDbChannelVolumeList = [NSMutableArray array];
277 |
278 | for (NSNumber *aChannelVolume in iChannelVolumeList) {
279 | float dB = 20 * log10(aChannelVolume.floatValue);
280 |
281 | if (aChannelVolume.floatValue <= 0.0f) {
282 | dB = -160.0f;//set min to -160.0f
283 | }
284 |
285 | [aDbChannelVolumeList addObject:@(dB)];
286 | }
287 |
288 | return aDbChannelVolumeList;
289 | }
290 |
291 | @end
292 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Resources/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension/Classes/AudioProcessing/MYAudioTapProcessor.m:
--------------------------------------------------------------------------------
1 | /*
2 | File: MYAudioTapProcessor.m
3 | Abstract: Audio tap processor using MTAudioProcessingTap for audio visualization and processing.
4 | Version: 1.0.1
5 |
6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 | Inc. ("Apple") in consideration of your agreement to the following
8 | terms, and your use, installation, modification or redistribution of
9 | this Apple software constitutes acceptance of these terms. If you do
10 | not agree with these terms, please do not use, install, modify or
11 | redistribute this Apple software.
12 |
13 | In consideration of your agreement to abide by the following terms, and
14 | subject to these terms, Apple grants you a personal, non-exclusive
15 | license, under Apple's copyrights in this original Apple software (the
16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 | Software, with or without modifications, in source and/or binary forms;
18 | provided that if you redistribute the Apple Software in its entirety and
19 | without modifications, you must retain this notice and the following
20 | text and disclaimers in all such redistributions of the Apple Software.
21 | Neither the name, trademarks, service marks or logos of Apple Inc. may
22 | be used to endorse or promote products derived from the Apple Software
23 | without specific prior written permission from Apple. Except as
24 | expressly stated in this notice, no other rights or licenses, express or
25 | implied, are granted by Apple herein, including but not limited to any
26 | patent rights that may be infringed by your derivative works or by other
27 | works in which the Apple Software may be incorporated.
28 |
29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 |
35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 | POSSIBILITY OF SUCH DAMAGE.
43 |
44 | Copyright (C) 2013 Apple Inc. All Rights Reserved.
45 |
46 | Modified to add additional methods
47 | */
48 |
49 | #import "MYAudioTapProcessor.h"
50 |
51 | #import
52 |
53 | // This struct is used to pass along data between the MTAudioProcessingTap callbacks.
54 | typedef struct AVAudioTapProcessorContext {
55 | Boolean supportedTapProcessingFormat;
56 | Boolean isNonInterleaved;
57 | Float64 sampleRate;
58 | AudioUnit audioUnit;
59 | Float64 sampleCount;
60 | float leftChannelVolume;
61 | float rightChannelVolume;
62 | float *channelVolumeList;
63 | float numberOfChannels;
64 | AudioBufferList *bufferList;
65 | AVAudioFrameCount numberOfFrames;
66 | void *self;
67 | } AVAudioTapProcessorContext;
68 |
69 | // MTAudioProcessingTap callbacks.
70 | static void tap_InitCallback(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut);
71 | static void tap_FinalizeCallback(MTAudioProcessingTapRef tap);
72 | static void tap_PrepareCallback(MTAudioProcessingTapRef tap, CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat);
73 | static void tap_UnprepareCallback(MTAudioProcessingTapRef tap);
74 | static void tap_ProcessCallback(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut);
75 |
76 | // Audio Unit callbacks.
77 | static OSStatus AU_RenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData);
78 |
79 | @interface MYAudioTapProcessor ()
80 | {
81 | AVAudioMix *_audioMix;
82 | }
83 |
84 | @property (nonatomic, nullable) AVAudioFormat *format;
85 |
86 | @end
87 |
88 |
89 | @implementation MYAudioTapProcessor
90 |
91 |
92 | - (id)initWithAudioAssetTrack:(AVAssetTrack *)audioAssetTrack
93 | {
94 | NSParameterAssert(audioAssetTrack && [audioAssetTrack.mediaType isEqualToString:AVMediaTypeAudio]);
95 |
96 | self = [super init];
97 |
98 | if (self)
99 | {
100 | _audioAssetTrack = audioAssetTrack;
101 | _centerFrequency = (4980.0f / 23980.0f); // equals 5000 Hz (assuming sample rate is 48k)
102 | _bandwidth = (500.0f / 11900.0f); // equals 600 Cents
103 | _numberOfChannels = -1;
104 | }
105 |
106 | return self;
107 | }
108 |
109 | #pragma mark - Properties
110 |
111 | - (AVAudioMix *)audioMix
112 | {
113 | if (!_audioMix)
114 | {
115 | AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
116 | if (audioMix)
117 | {
118 | AVMutableAudioMixInputParameters *audioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:self.audioAssetTrack];
119 | if (audioMixInputParameters)
120 | {
121 | MTAudioProcessingTapCallbacks callbacks;
122 |
123 | callbacks.version = kMTAudioProcessingTapCallbacksVersion_0;
124 | callbacks.clientInfo = (__bridge void *)self;
125 | callbacks.init = tap_InitCallback;
126 | callbacks.finalize = tap_FinalizeCallback;
127 | callbacks.prepare = tap_PrepareCallback;
128 | callbacks.unprepare = tap_UnprepareCallback;
129 | callbacks.process = tap_ProcessCallback;
130 |
131 | MTAudioProcessingTapRef audioProcessingTap;
132 | if (noErr == MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PreEffects, &audioProcessingTap))
133 | {
134 | audioMixInputParameters.audioTapProcessor = audioProcessingTap;
135 |
136 | CFRelease(audioProcessingTap);
137 |
138 | audioMix.inputParameters = @[audioMixInputParameters];
139 |
140 | _audioMix = audioMix;
141 | }
142 | }
143 | }
144 | }
145 |
146 | return _audioMix;
147 | }
148 |
149 | - (void)setCenterFrequency:(float)centerFrequency
150 | {
151 | if (_centerFrequency != centerFrequency)
152 | {
153 | _centerFrequency = centerFrequency;
154 |
155 | AVAudioMix *audioMix = self.audioMix;
156 | if (audioMix)
157 | {
158 | // Get pointer to Audio Unit stored in MTAudioProcessingTap context.
159 | MTAudioProcessingTapRef audioProcessingTap = ((AVMutableAudioMixInputParameters *)audioMix.inputParameters[0]).audioTapProcessor;
160 | AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(audioProcessingTap);
161 | AudioUnit audioUnit = context->audioUnit;
162 | if (audioUnit)
163 | {
164 | // Update center frequency of bandpass filter Audio Unit.
165 | Float32 newCenterFrequency = (20.0f + ((context->sampleRate * 0.5f) - 20.0f) * self.centerFrequency); // Global, Hz, 20->(SampleRate/2), 5000
166 | OSStatus status = AudioUnitSetParameter(audioUnit, kBandpassParam_CenterFrequency, kAudioUnitScope_Global, 0, newCenterFrequency, 0);
167 | if (noErr != status)
168 | NSLog(@"AudioUnitSetParameter(kBandpassParam_CenterFrequency): %d", (int)status);
169 | }
170 | }
171 | }
172 | }
173 |
174 | - (void)setBandwidth:(float)bandwidth
175 | {
176 | if (_bandwidth != bandwidth)
177 | {
178 | _bandwidth = bandwidth;
179 |
180 | AVAudioMix *audioMix = self.audioMix;
181 | if (audioMix)
182 | {
183 | // Get pointer to Audio Unit stored in MTAudioProcessingTap context.
184 | MTAudioProcessingTapRef audioProcessingTap = ((AVMutableAudioMixInputParameters *)audioMix.inputParameters[0]).audioTapProcessor;
185 | AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(audioProcessingTap);
186 | AudioUnit audioUnit = context->audioUnit;
187 | if (audioUnit)
188 | {
189 | // Update bandwidth of bandpass filter Audio Unit.
190 | Float32 newBandwidth = (100.0f + 11900.0f * self.bandwidth);
191 | OSStatus status = AudioUnitSetParameter(audioUnit, kBandpassParam_Bandwidth, kAudioUnitScope_Global, 0, newBandwidth, 0); // Global, Cents, 100->12000, 600
192 | if (noErr != status)
193 | NSLog(@"AudioUnitSetParameter(kBandpassParam_Bandwidth): %d", (int)status);
194 | }
195 | }
196 | }
197 | }
198 |
199 | #pragma mark -
200 |
201 | - (void)updateLeftChannelVolume:(float)leftChannelVolume rightChannelVolume:(float)rightChannelVolume
202 | {
203 | @autoreleasepool
204 | {
205 | dispatch_async(dispatch_get_main_queue(), ^{
206 | // Forward left and right channel volume to delegate.
207 | if (self.delegate && [self.delegate respondsToSelector:@selector(audioTabProcessor:hasNewLeftChannelValue:rightChannelValue:)])
208 | [self.delegate audioTabProcessor:self hasNewLeftChannelValue:leftChannelVolume rightChannelValue:rightChannelVolume];
209 | });
210 | }
211 | }
212 |
213 |
214 | - (void)updateChannelVolumeList:(float *)channelVolumeList withChannelVolumeListCount:(UInt32)iCount {
215 | @autoreleasepool
216 | {
217 | dispatch_async(dispatch_get_main_queue(), ^{
218 |
219 | NSMutableArray *aVolumeList = [NSMutableArray array];
220 | for (int i = 0; i < iCount; i++) {
221 | [aVolumeList addObject:[NSNumber numberWithFloat:channelVolumeList[i]]];
222 | }
223 |
224 | if (self.numberOfChannels != iCount) {
225 | self.numberOfChannels = (int)iCount;
226 | }
227 |
228 | // Forward left and right channel volume to delegate.
229 | if (self.delegate && [self.delegate respondsToSelector:@selector(audioTabProcessor:hasNewChannelVolumeList:)]) {
230 | [self.delegate audioTabProcessor:self hasNewChannelVolumeList:aVolumeList];
231 | }
232 | });
233 | }
234 | }
235 |
236 |
237 | - (void)updateWithAudioBuffer:(NSValue *)bufferList capacity:(AVAudioFrameCount)capacity {
238 | AudioBufferList *list = bufferList.pointerValue;
239 |
240 | AudioBuffer *pBuffer = &list->mBuffers[0];
241 | AVAudioPCMBuffer *outBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.format frameCapacity:capacity];
242 | outBuffer.frameLength = pBuffer->mDataByteSize / sizeof(float);
243 | float *pData = (float *)pBuffer->mData;
244 | memcpy(outBuffer.floatChannelData[0], pData, pBuffer->mDataByteSize);
245 | if (self.numberOfChannels > 1) {
246 | memcpy(outBuffer.floatChannelData[1], pData, pBuffer->mDataByteSize);
247 | }
248 | [self.delegate audioTabProcessor:self didReceiveBuffer:outBuffer];
249 | }
250 |
251 | - (void)stopProcessing {
252 | NSLog(@"AudioTapProcessor - stopProcessing");
253 | AVMutableAudioMixInputParameters *params = (AVMutableAudioMixInputParameters *)_audioMix.inputParameters[0];
254 | MTAudioProcessingTapRef audioProcessingTap = params.audioTapProcessor;
255 |
256 | if (audioProcessingTap == NULL)
257 | return;
258 |
259 | AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(audioProcessingTap);
260 |
261 | // nils out the pointer so that we know in tapProcessorCallbacks that self will be dealloc'ed
262 | context->self = NULL;
263 | }
264 |
265 | @end
266 |
267 |
268 | #pragma mark - MTAudioProcessingTap Callbacks
269 |
270 | static void tap_InitCallback(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut)
271 | {
272 | AVAudioTapProcessorContext *context = calloc(1, sizeof(AVAudioTapProcessorContext));
273 |
274 | // Initialize MTAudioProcessingTap context.
275 | context->supportedTapProcessingFormat = false;
276 | context->isNonInterleaved = false;
277 | context->sampleRate = NAN;
278 | context->audioUnit = NULL;
279 | context->sampleCount = 0.0f;
280 | context->leftChannelVolume = 0.0f;
281 | context->rightChannelVolume = 0.0f;
282 | context->channelVolumeList = NULL;
283 | context->numberOfChannels = 0.0f;
284 | context->bufferList = NULL;
285 | context->numberOfFrames = 0;
286 | context->self = clientInfo;
287 |
288 | *tapStorageOut = context;
289 | }
290 |
291 | static void tap_FinalizeCallback(MTAudioProcessingTapRef tap)
292 | {
293 | AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(tap);
294 |
295 | // Clear MTAudioProcessingTap context.
296 | context->self = NULL;
297 |
298 | free(context);
299 | }
300 |
301 | static void tap_PrepareCallback(MTAudioProcessingTapRef tap, CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat)
302 | {
303 | AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(tap);
304 |
305 | MYAudioTapProcessor *self = ((__bridge MYAudioTapProcessor *)context->self);
306 | self.format = [[AVAudioFormat alloc] initWithStreamDescription:processingFormat];
307 |
308 | // Store sample rate for -setCenterFrequency:.
309 | context->sampleRate = processingFormat->mSampleRate;
310 |
311 | /* Verify processing format (this is not needed for Audio Unit, but for RMS calculation). */
312 |
313 | context->supportedTapProcessingFormat = true;
314 |
315 | if (processingFormat->mFormatID != kAudioFormatLinearPCM)
316 | {
317 | NSLog(@"Unsupported audio format ID for audioProcessingTap. LinearPCM only.");
318 | context->supportedTapProcessingFormat = false;
319 | }
320 |
321 | if (!(processingFormat->mFormatFlags & kAudioFormatFlagIsFloat))
322 | {
323 | NSLog(@"Unsupported audio format flag for audioProcessingTap. Float only.");
324 | context->supportedTapProcessingFormat = false;
325 | }
326 |
327 | if (processingFormat->mFormatFlags & kAudioFormatFlagIsNonInterleaved)
328 | {
329 | context->isNonInterleaved = true;
330 | }
331 |
332 | /* Create bandpass filter Audio Unit */
333 |
334 | AudioUnit audioUnit;
335 |
336 | AudioComponentDescription audioComponentDescription;
337 | audioComponentDescription.componentType = kAudioUnitType_Effect;
338 | audioComponentDescription.componentSubType = kAudioUnitSubType_BandPassFilter;
339 | audioComponentDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
340 | audioComponentDescription.componentFlags = 0;
341 | audioComponentDescription.componentFlagsMask = 0;
342 |
343 | AudioComponent audioComponent = AudioComponentFindNext(NULL, &audioComponentDescription);
344 | if (audioComponent)
345 | {
346 | if (noErr == AudioComponentInstanceNew(audioComponent, &audioUnit))
347 | {
348 | OSStatus status = noErr;
349 |
350 | // Set audio unit input/output stream format to processing format.
351 | if (noErr == status)
352 | {
353 | status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, processingFormat, sizeof(AudioStreamBasicDescription));
354 | }
355 | if (noErr == status)
356 | {
357 | status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, processingFormat, sizeof(AudioStreamBasicDescription));
358 | }
359 |
360 | // Set audio unit render callback.
361 | if (noErr == status)
362 | {
363 | AURenderCallbackStruct renderCallbackStruct;
364 | renderCallbackStruct.inputProc = AU_RenderCallback;
365 | renderCallbackStruct.inputProcRefCon = (void *)tap;
366 | status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct));
367 | }
368 |
369 | // Set audio unit maximum frames per slice to max frames.
370 | if (noErr == status)
371 | {
372 | UInt32 maximumFramesPerSlice = (UInt32)maxFrames;
373 | status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maximumFramesPerSlice, (UInt32)sizeof(UInt32));
374 | }
375 |
376 | // Initialize audio unit.
377 | if (noErr == status)
378 | {
379 | status = AudioUnitInitialize(audioUnit);
380 | }
381 |
382 | if (noErr != status)
383 | {
384 | AudioComponentInstanceDispose(audioUnit);
385 | audioUnit = NULL;
386 | }
387 |
388 | context->audioUnit = audioUnit;
389 | }
390 | }
391 | }
392 |
393 | static void tap_UnprepareCallback(MTAudioProcessingTapRef tap)
394 | {
395 | AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(tap);
396 |
397 | /* Release bandpass filter Audio Unit */
398 |
399 | if (context->audioUnit)
400 | {
401 | AudioUnitUninitialize(context->audioUnit);
402 | AudioComponentInstanceDispose(context->audioUnit);
403 | context->audioUnit = NULL;
404 | }
405 |
406 | if (context->channelVolumeList) {
407 | free(context->channelVolumeList);
408 | context->channelVolumeList = NULL;
409 | }
410 | }
411 |
412 | static void tap_ProcessCallback(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut)
413 | {
414 | AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(tap);
415 |
416 | OSStatus status;
417 |
418 | // Skip processing when format not supported.
419 | if (!context->supportedTapProcessingFormat)
420 | {
421 | NSLog(@"Unsupported tap processing format.");
422 | return;
423 | }
424 |
425 | MYAudioTapProcessor *self = ((__bridge MYAudioTapProcessor *)context->self);
426 |
427 | if (!self) {
428 | NSLog(@"AudioTapProcessor - processCallback CANCELLED (self is nil)");
429 | return;
430 | }
431 |
432 | if (self.isBandpassFilterEnabled)
433 | {
434 | // Apply bandpass filter Audio Unit.
435 | AudioUnit audioUnit = context->audioUnit;
436 | if (audioUnit)
437 | {
438 | AudioTimeStamp audioTimeStamp;
439 | audioTimeStamp.mSampleTime = context->sampleCount;
440 | audioTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
441 |
442 | status = AudioUnitRender(audioUnit, 0, &audioTimeStamp, 0, (UInt32)numberFrames, bufferListInOut);
443 | if (noErr != status)
444 | {
445 | NSLog(@"AudioUnitRender(): %d", (int)status);
446 | return;
447 | }
448 |
449 | // Increment sample count for audio unit.
450 | context->sampleCount += numberFrames;
451 |
452 | // Set number of frames out.
453 | *numberFramesOut = numberFrames;
454 | }
455 | }
456 | else
457 | {
458 | // Get actual audio buffers from MTAudioProcessingTap (AudioUnitRender() will fill bufferListInOut otherwise).
459 | status = MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, flagsOut, NULL, numberFramesOut);
460 | if (noErr != status)
461 | {
462 | NSLog(@"MTAudioProcessingTapGetSourceAudio: %d", (int)status);
463 | return;
464 | }
465 | }
466 |
467 | UInt32 aCount = bufferListInOut->mNumberBuffers;
468 |
469 | context->numberOfChannels = (float)aCount;
470 |
471 | if (aCount > 0) {
472 | if (context->channelVolumeList) {
473 | free(context->channelVolumeList);
474 | context->channelVolumeList = NULL;
475 | }
476 | context->channelVolumeList = malloc(aCount * sizeof(float));
477 |
478 | if (context->channelVolumeList == 0) {
479 | NSLog(@"Error! could not initialize channel volume list");
480 | }
481 | }
482 |
483 | context->bufferList = bufferListInOut;
484 | context->numberOfFrames = (AVAudioFrameCount)numberFrames;
485 |
486 | NSValue *audioBufferList = [NSValue valueWithBytes:&bufferListInOut objCType:@encode(AudioBufferList *)];
487 |
488 | // Calculate root mean square (RMS) for left and right audio channel.
489 | for (UInt32 i = 0; i < bufferListInOut->mNumberBuffers; i++)
490 | {
491 | AudioBuffer *pBuffer = &bufferListInOut->mBuffers[i];
492 | UInt32 cSamples = (UInt32) (numberFrames * (context->isNonInterleaved ? 1 : pBuffer->mNumberChannels));
493 |
494 | float *pData = (float *)pBuffer->mData;
495 |
496 | float rms = 0.0f;
497 | for (UInt32 j = 0; j < cSamples; j++)
498 | {
499 | rms += pData[j] * pData[j];
500 | }
501 | if (cSamples > 0)
502 | {
503 | rms = sqrtf(rms / cSamples);
504 | }
505 |
506 | if (0 == i)
507 | {
508 | context->leftChannelVolume = rms;
509 | }
510 | if (1 == i || (0 == i && 1 == bufferListInOut->mNumberBuffers))
511 | {
512 | context->rightChannelVolume = rms;
513 | }
514 |
515 | context->channelVolumeList[i] = rms;
516 | }
517 |
518 | // Pass calculated left and right channel volume to VU meters.
519 | [self updateLeftChannelVolume:context->leftChannelVolume rightChannelVolume:context->rightChannelVolume];
520 | [self updateChannelVolumeList:context->channelVolumeList withChannelVolumeListCount:aCount];
521 | [self updateWithAudioBuffer:audioBufferList capacity:(AVAudioFrameCount)numberFrames];
522 | }
523 |
524 | #pragma mark - Audio Unit Callbacks
525 |
526 | OSStatus AU_RenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
527 | {
528 | // Just return audio buffers from MTAudioProcessingTap.
529 | return MTAudioProcessingTapGetSourceAudio(inRefCon, inNumberFrames, ioData, NULL, NULL, NULL);
530 | }
531 |
--------------------------------------------------------------------------------
/ACBAVPlayerExtension.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | E912446B2002FFCE00DC8139 /* MYAudioTapProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE1721F3D7DBC005EF6B1 /* MYAudioTapProcessor.m */; };
11 | E950DDBC200211B3002F56AE /* ACBAVPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E950DDB3200211B3002F56AE /* ACBAVPlayer.framework */; };
12 | E950DDC3200211B3002F56AE /* ACBAVPlayerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950DDC2200211B3002F56AE /* ACBAVPlayerTests.swift */; };
13 | E950DDC5200211B3002F56AE /* ACBAVPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = E950DDB5200211B3002F56AE /* ACBAVPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
14 | E950DDC8200211B3002F56AE /* ACBAVPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E950DDB3200211B3002F56AE /* ACBAVPlayer.framework */; };
15 | E950DDCA200211B3002F56AE /* ACBAVPlayer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E950DDB3200211B3002F56AE /* ACBAVPlayer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
16 | E950DDD1200211B7002F56AE /* AVPlayer+ACBHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE1701F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.m */; };
17 | E950DDD2200211B9002F56AE /* ACBAudioProcessHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE16E1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.m */; };
18 | E950DDD4200211D3002F56AE /* AVPlayer+ACBHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = E99BE16F1F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.h */; settings = {ATTRIBUTES = (Public, ); }; };
19 | E950DDD5200211D3002F56AE /* ACBAudioProcessHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = E99BE16D1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.h */; };
20 | E950DDD6200211D3002F56AE /* MYAudioTapProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = E99BE1711F3D7DBC005EF6B1 /* MYAudioTapProcessor.h */; };
21 | E950DDD920021247002F56AE /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E950DDD820021247002F56AE /* AVFoundation.framework */; };
22 | E99BE1501F3D7D09005EF6B1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE14F1F3D7D09005EF6B1 /* main.m */; };
23 | E99BE1791F3D7DBC005EF6B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E99BE1661F3D7DBC005EF6B1 /* Assets.xcassets */; };
24 | E99BE17A1F3D7DBC005EF6B1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E99BE1671F3D7DBC005EF6B1 /* LaunchScreen.storyboard */; };
25 | E99BE17B1F3D7DBC005EF6B1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E99BE1691F3D7DBC005EF6B1 /* Main.storyboard */; };
26 | E99BE17C1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE16E1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.m */; };
27 | E99BE17D1F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE1701F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.m */; };
28 | E99BE17E1F3D7DBC005EF6B1 /* MYAudioTapProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE1721F3D7DBC005EF6B1 /* MYAudioTapProcessor.m */; };
29 | E99BE17F1F3D7DBC005EF6B1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE1751F3D7DBC005EF6B1 /* AppDelegate.m */; };
30 | E99BE1801F3D7DBC005EF6B1 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E99BE1781F3D7DBC005EF6B1 /* ViewController.m */; };
31 | /* End PBXBuildFile section */
32 |
33 | /* Begin PBXContainerItemProxy section */
34 | E950DDBD200211B3002F56AE /* PBXContainerItemProxy */ = {
35 | isa = PBXContainerItemProxy;
36 | containerPortal = E99BE1431F3D7D09005EF6B1 /* Project object */;
37 | proxyType = 1;
38 | remoteGlobalIDString = E950DDB2200211B3002F56AE;
39 | remoteInfo = ACBAVPlayer;
40 | };
41 | E950DDBF200211B3002F56AE /* PBXContainerItemProxy */ = {
42 | isa = PBXContainerItemProxy;
43 | containerPortal = E99BE1431F3D7D09005EF6B1 /* Project object */;
44 | proxyType = 1;
45 | remoteGlobalIDString = E99BE14A1F3D7D09005EF6B1;
46 | remoteInfo = ACBAVPlayerExtension;
47 | };
48 | E950DDC6200211B3002F56AE /* PBXContainerItemProxy */ = {
49 | isa = PBXContainerItemProxy;
50 | containerPortal = E99BE1431F3D7D09005EF6B1 /* Project object */;
51 | proxyType = 1;
52 | remoteGlobalIDString = E950DDB2200211B3002F56AE;
53 | remoteInfo = ACBAVPlayer;
54 | };
55 | /* End PBXContainerItemProxy section */
56 |
57 | /* Begin PBXCopyFilesBuildPhase section */
58 | E950DDC9200211B3002F56AE /* Embed Frameworks */ = {
59 | isa = PBXCopyFilesBuildPhase;
60 | buildActionMask = 2147483647;
61 | dstPath = "";
62 | dstSubfolderSpec = 10;
63 | files = (
64 | E950DDCA200211B3002F56AE /* ACBAVPlayer.framework in Embed Frameworks */,
65 | );
66 | name = "Embed Frameworks";
67 | runOnlyForDeploymentPostprocessing = 0;
68 | };
69 | /* End PBXCopyFilesBuildPhase section */
70 |
71 | /* Begin PBXFileReference section */
72 | E950DDB3200211B3002F56AE /* ACBAVPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ACBAVPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
73 | E950DDB5200211B3002F56AE /* ACBAVPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ACBAVPlayer.h; sourceTree = ""; };
74 | E950DDB6200211B3002F56AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
75 | E950DDBB200211B3002F56AE /* ACBAVPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ACBAVPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
76 | E950DDC2200211B3002F56AE /* ACBAVPlayerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACBAVPlayerTests.swift; sourceTree = ""; };
77 | E950DDC4200211B3002F56AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
78 | E950DDD820021247002F56AE /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
79 | E99BE14B1F3D7D09005EF6B1 /* ACBAVPlayerExtension.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ACBAVPlayerExtension.app; sourceTree = BUILT_PRODUCTS_DIR; };
80 | E99BE14F1F3D7D09005EF6B1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
81 | E99BE15F1F3D7D09005EF6B1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
82 | E99BE1661F3D7DBC005EF6B1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
83 | E99BE1681F3D7DBC005EF6B1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
84 | E99BE16A1F3D7DBC005EF6B1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
85 | E99BE16D1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACBAudioProcessHelper.h; sourceTree = ""; };
86 | E99BE16E1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACBAudioProcessHelper.m; sourceTree = ""; };
87 | E99BE16F1F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AVPlayer+ACBHelper.h"; sourceTree = ""; };
88 | E99BE1701F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AVPlayer+ACBHelper.m"; sourceTree = ""; };
89 | E99BE1711F3D7DBC005EF6B1 /* MYAudioTapProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYAudioTapProcessor.h; sourceTree = ""; };
90 | E99BE1721F3D7DBC005EF6B1 /* MYAudioTapProcessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYAudioTapProcessor.m; sourceTree = ""; };
91 | E99BE1741F3D7DBC005EF6B1 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
92 | E99BE1751F3D7DBC005EF6B1 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
93 | E99BE1771F3D7DBC005EF6B1 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
94 | E99BE1781F3D7DBC005EF6B1 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
95 | /* End PBXFileReference section */
96 |
97 | /* Begin PBXFrameworksBuildPhase section */
98 | E950DDAF200211B3002F56AE /* Frameworks */ = {
99 | isa = PBXFrameworksBuildPhase;
100 | buildActionMask = 2147483647;
101 | files = (
102 | E950DDD920021247002F56AE /* AVFoundation.framework in Frameworks */,
103 | );
104 | runOnlyForDeploymentPostprocessing = 0;
105 | };
106 | E950DDB8200211B3002F56AE /* Frameworks */ = {
107 | isa = PBXFrameworksBuildPhase;
108 | buildActionMask = 2147483647;
109 | files = (
110 | E950DDBC200211B3002F56AE /* ACBAVPlayer.framework in Frameworks */,
111 | );
112 | runOnlyForDeploymentPostprocessing = 0;
113 | };
114 | E99BE1481F3D7D09005EF6B1 /* Frameworks */ = {
115 | isa = PBXFrameworksBuildPhase;
116 | buildActionMask = 2147483647;
117 | files = (
118 | E950DDC8200211B3002F56AE /* ACBAVPlayer.framework in Frameworks */,
119 | );
120 | runOnlyForDeploymentPostprocessing = 0;
121 | };
122 | /* End PBXFrameworksBuildPhase section */
123 |
124 | /* Begin PBXGroup section */
125 | E950DDB4200211B3002F56AE /* ACBAVPlayer */ = {
126 | isa = PBXGroup;
127 | children = (
128 | E950DDB5200211B3002F56AE /* ACBAVPlayer.h */,
129 | E950DDB6200211B3002F56AE /* Info.plist */,
130 | );
131 | path = ACBAVPlayer;
132 | sourceTree = "";
133 | };
134 | E950DDC1200211B3002F56AE /* ACBAVPlayerTests */ = {
135 | isa = PBXGroup;
136 | children = (
137 | E950DDC2200211B3002F56AE /* ACBAVPlayerTests.swift */,
138 | E950DDC4200211B3002F56AE /* Info.plist */,
139 | );
140 | path = ACBAVPlayerTests;
141 | sourceTree = "";
142 | };
143 | E950DDD720021246002F56AE /* Frameworks */ = {
144 | isa = PBXGroup;
145 | children = (
146 | E950DDD820021247002F56AE /* AVFoundation.framework */,
147 | );
148 | name = Frameworks;
149 | sourceTree = "";
150 | };
151 | E99BE1421F3D7D09005EF6B1 = {
152 | isa = PBXGroup;
153 | children = (
154 | E99BE14D1F3D7D09005EF6B1 /* ACBAVPlayerExtension */,
155 | E950DDB4200211B3002F56AE /* ACBAVPlayer */,
156 | E950DDC1200211B3002F56AE /* ACBAVPlayerTests */,
157 | E99BE14C1F3D7D09005EF6B1 /* Products */,
158 | E950DDD720021246002F56AE /* Frameworks */,
159 | );
160 | sourceTree = "";
161 | };
162 | E99BE14C1F3D7D09005EF6B1 /* Products */ = {
163 | isa = PBXGroup;
164 | children = (
165 | E99BE14B1F3D7D09005EF6B1 /* ACBAVPlayerExtension.app */,
166 | E950DDB3200211B3002F56AE /* ACBAVPlayer.framework */,
167 | E950DDBB200211B3002F56AE /* ACBAVPlayerTests.xctest */,
168 | );
169 | name = Products;
170 | sourceTree = "";
171 | };
172 | E99BE14D1F3D7D09005EF6B1 /* ACBAVPlayerExtension */ = {
173 | isa = PBXGroup;
174 | children = (
175 | E99BE16B1F3D7DBC005EF6B1 /* Classes */,
176 | E99BE1651F3D7DBC005EF6B1 /* Resources */,
177 | E99BE14E1F3D7D09005EF6B1 /* Supporting Files */,
178 | );
179 | path = ACBAVPlayerExtension;
180 | sourceTree = "";
181 | };
182 | E99BE14E1F3D7D09005EF6B1 /* Supporting Files */ = {
183 | isa = PBXGroup;
184 | children = (
185 | E99BE15F1F3D7D09005EF6B1 /* Info.plist */,
186 | E99BE14F1F3D7D09005EF6B1 /* main.m */,
187 | );
188 | name = "Supporting Files";
189 | sourceTree = "";
190 | };
191 | E99BE1651F3D7DBC005EF6B1 /* Resources */ = {
192 | isa = PBXGroup;
193 | children = (
194 | E99BE1661F3D7DBC005EF6B1 /* Assets.xcassets */,
195 | E99BE1671F3D7DBC005EF6B1 /* LaunchScreen.storyboard */,
196 | E99BE1691F3D7DBC005EF6B1 /* Main.storyboard */,
197 | );
198 | path = Resources;
199 | sourceTree = "";
200 | };
201 | E99BE16B1F3D7DBC005EF6B1 /* Classes */ = {
202 | isa = PBXGroup;
203 | children = (
204 | E99BE1731F3D7DBC005EF6B1 /* General */,
205 | E99BE16C1F3D7DBC005EF6B1 /* AudioProcessing */,
206 | E99BE1761F3D7DBC005EF6B1 /* ViewControllers */,
207 | );
208 | path = Classes;
209 | sourceTree = "";
210 | };
211 | E99BE16C1F3D7DBC005EF6B1 /* AudioProcessing */ = {
212 | isa = PBXGroup;
213 | children = (
214 | E99BE16F1F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.h */,
215 | E99BE1701F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.m */,
216 | E99BE16D1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.h */,
217 | E99BE16E1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.m */,
218 | E99BE1711F3D7DBC005EF6B1 /* MYAudioTapProcessor.h */,
219 | E99BE1721F3D7DBC005EF6B1 /* MYAudioTapProcessor.m */,
220 | );
221 | path = AudioProcessing;
222 | sourceTree = "";
223 | };
224 | E99BE1731F3D7DBC005EF6B1 /* General */ = {
225 | isa = PBXGroup;
226 | children = (
227 | E99BE1741F3D7DBC005EF6B1 /* AppDelegate.h */,
228 | E99BE1751F3D7DBC005EF6B1 /* AppDelegate.m */,
229 | );
230 | path = General;
231 | sourceTree = "";
232 | };
233 | E99BE1761F3D7DBC005EF6B1 /* ViewControllers */ = {
234 | isa = PBXGroup;
235 | children = (
236 | E99BE1771F3D7DBC005EF6B1 /* ViewController.h */,
237 | E99BE1781F3D7DBC005EF6B1 /* ViewController.m */,
238 | );
239 | path = ViewControllers;
240 | sourceTree = "";
241 | };
242 | /* End PBXGroup section */
243 |
244 | /* Begin PBXHeadersBuildPhase section */
245 | E950DDB0200211B3002F56AE /* Headers */ = {
246 | isa = PBXHeadersBuildPhase;
247 | buildActionMask = 2147483647;
248 | files = (
249 | E950DDC5200211B3002F56AE /* ACBAVPlayer.h in Headers */,
250 | E950DDD4200211D3002F56AE /* AVPlayer+ACBHelper.h in Headers */,
251 | E950DDD5200211D3002F56AE /* ACBAudioProcessHelper.h in Headers */,
252 | E950DDD6200211D3002F56AE /* MYAudioTapProcessor.h in Headers */,
253 | );
254 | runOnlyForDeploymentPostprocessing = 0;
255 | };
256 | /* End PBXHeadersBuildPhase section */
257 |
258 | /* Begin PBXNativeTarget section */
259 | E950DDB2200211B3002F56AE /* ACBAVPlayer */ = {
260 | isa = PBXNativeTarget;
261 | buildConfigurationList = E950DDCF200211B3002F56AE /* Build configuration list for PBXNativeTarget "ACBAVPlayer" */;
262 | buildPhases = (
263 | E950DDAE200211B3002F56AE /* Sources */,
264 | E950DDAF200211B3002F56AE /* Frameworks */,
265 | E950DDB0200211B3002F56AE /* Headers */,
266 | E950DDB1200211B3002F56AE /* Resources */,
267 | );
268 | buildRules = (
269 | );
270 | dependencies = (
271 | );
272 | name = ACBAVPlayer;
273 | productName = ACBAVPlayer;
274 | productReference = E950DDB3200211B3002F56AE /* ACBAVPlayer.framework */;
275 | productType = "com.apple.product-type.framework";
276 | };
277 | E950DDBA200211B3002F56AE /* ACBAVPlayerTests */ = {
278 | isa = PBXNativeTarget;
279 | buildConfigurationList = E950DDD0200211B3002F56AE /* Build configuration list for PBXNativeTarget "ACBAVPlayerTests" */;
280 | buildPhases = (
281 | E950DDB7200211B3002F56AE /* Sources */,
282 | E950DDB8200211B3002F56AE /* Frameworks */,
283 | E950DDB9200211B3002F56AE /* Resources */,
284 | );
285 | buildRules = (
286 | );
287 | dependencies = (
288 | E950DDBE200211B3002F56AE /* PBXTargetDependency */,
289 | E950DDC0200211B3002F56AE /* PBXTargetDependency */,
290 | );
291 | name = ACBAVPlayerTests;
292 | productName = ACBAVPlayerTests;
293 | productReference = E950DDBB200211B3002F56AE /* ACBAVPlayerTests.xctest */;
294 | productType = "com.apple.product-type.bundle.unit-test";
295 | };
296 | E99BE14A1F3D7D09005EF6B1 /* ACBAVPlayerExtension */ = {
297 | isa = PBXNativeTarget;
298 | buildConfigurationList = E99BE1621F3D7D09005EF6B1 /* Build configuration list for PBXNativeTarget "ACBAVPlayerExtension" */;
299 | buildPhases = (
300 | E99BE1471F3D7D09005EF6B1 /* Sources */,
301 | E99BE1481F3D7D09005EF6B1 /* Frameworks */,
302 | E99BE1491F3D7D09005EF6B1 /* Resources */,
303 | E950DDC9200211B3002F56AE /* Embed Frameworks */,
304 | );
305 | buildRules = (
306 | );
307 | dependencies = (
308 | E950DDC7200211B3002F56AE /* PBXTargetDependency */,
309 | );
310 | name = ACBAVPlayerExtension;
311 | productName = ACBAVPlayerExtension;
312 | productReference = E99BE14B1F3D7D09005EF6B1 /* ACBAVPlayerExtension.app */;
313 | productType = "com.apple.product-type.application";
314 | };
315 | /* End PBXNativeTarget section */
316 |
317 | /* Begin PBXProject section */
318 | E99BE1431F3D7D09005EF6B1 /* Project object */ = {
319 | isa = PBXProject;
320 | attributes = {
321 | BuildIndependentTargetsInParallel = YES;
322 | LastSwiftUpdateCheck = 0920;
323 | LastUpgradeCheck = 1540;
324 | ORGANIZATIONNAME = akhil;
325 | TargetAttributes = {
326 | E950DDB2200211B3002F56AE = {
327 | CreatedOnToolsVersion = 9.2;
328 | ProvisioningStyle = Automatic;
329 | };
330 | E950DDBA200211B3002F56AE = {
331 | CreatedOnToolsVersion = 9.2;
332 | LastSwiftMigration = 1540;
333 | ProvisioningStyle = Automatic;
334 | TestTargetID = E99BE14A1F3D7D09005EF6B1;
335 | };
336 | E99BE14A1F3D7D09005EF6B1 = {
337 | CreatedOnToolsVersion = 8.3.3;
338 | ProvisioningStyle = Automatic;
339 | };
340 | };
341 | };
342 | buildConfigurationList = E99BE1461F3D7D09005EF6B1 /* Build configuration list for PBXProject "ACBAVPlayerExtension" */;
343 | compatibilityVersion = "Xcode 3.2";
344 | developmentRegion = en;
345 | hasScannedForEncodings = 0;
346 | knownRegions = (
347 | en,
348 | Base,
349 | );
350 | mainGroup = E99BE1421F3D7D09005EF6B1;
351 | productRefGroup = E99BE14C1F3D7D09005EF6B1 /* Products */;
352 | projectDirPath = "";
353 | projectRoot = "";
354 | targets = (
355 | E99BE14A1F3D7D09005EF6B1 /* ACBAVPlayerExtension */,
356 | E950DDB2200211B3002F56AE /* ACBAVPlayer */,
357 | E950DDBA200211B3002F56AE /* ACBAVPlayerTests */,
358 | );
359 | };
360 | /* End PBXProject section */
361 |
362 | /* Begin PBXResourcesBuildPhase section */
363 | E950DDB1200211B3002F56AE /* Resources */ = {
364 | isa = PBXResourcesBuildPhase;
365 | buildActionMask = 2147483647;
366 | files = (
367 | );
368 | runOnlyForDeploymentPostprocessing = 0;
369 | };
370 | E950DDB9200211B3002F56AE /* Resources */ = {
371 | isa = PBXResourcesBuildPhase;
372 | buildActionMask = 2147483647;
373 | files = (
374 | );
375 | runOnlyForDeploymentPostprocessing = 0;
376 | };
377 | E99BE1491F3D7D09005EF6B1 /* Resources */ = {
378 | isa = PBXResourcesBuildPhase;
379 | buildActionMask = 2147483647;
380 | files = (
381 | E99BE1791F3D7DBC005EF6B1 /* Assets.xcassets in Resources */,
382 | E99BE17B1F3D7DBC005EF6B1 /* Main.storyboard in Resources */,
383 | E99BE17A1F3D7DBC005EF6B1 /* LaunchScreen.storyboard in Resources */,
384 | );
385 | runOnlyForDeploymentPostprocessing = 0;
386 | };
387 | /* End PBXResourcesBuildPhase section */
388 |
389 | /* Begin PBXSourcesBuildPhase section */
390 | E950DDAE200211B3002F56AE /* Sources */ = {
391 | isa = PBXSourcesBuildPhase;
392 | buildActionMask = 2147483647;
393 | files = (
394 | E912446B2002FFCE00DC8139 /* MYAudioTapProcessor.m in Sources */,
395 | E950DDD1200211B7002F56AE /* AVPlayer+ACBHelper.m in Sources */,
396 | E950DDD2200211B9002F56AE /* ACBAudioProcessHelper.m in Sources */,
397 | );
398 | runOnlyForDeploymentPostprocessing = 0;
399 | };
400 | E950DDB7200211B3002F56AE /* Sources */ = {
401 | isa = PBXSourcesBuildPhase;
402 | buildActionMask = 2147483647;
403 | files = (
404 | E950DDC3200211B3002F56AE /* ACBAVPlayerTests.swift in Sources */,
405 | );
406 | runOnlyForDeploymentPostprocessing = 0;
407 | };
408 | E99BE1471F3D7D09005EF6B1 /* Sources */ = {
409 | isa = PBXSourcesBuildPhase;
410 | buildActionMask = 2147483647;
411 | files = (
412 | E99BE17E1F3D7DBC005EF6B1 /* MYAudioTapProcessor.m in Sources */,
413 | E99BE1801F3D7DBC005EF6B1 /* ViewController.m in Sources */,
414 | E99BE17C1F3D7DBC005EF6B1 /* ACBAudioProcessHelper.m in Sources */,
415 | E99BE1501F3D7D09005EF6B1 /* main.m in Sources */,
416 | E99BE17D1F3D7DBC005EF6B1 /* AVPlayer+ACBHelper.m in Sources */,
417 | E99BE17F1F3D7DBC005EF6B1 /* AppDelegate.m in Sources */,
418 | );
419 | runOnlyForDeploymentPostprocessing = 0;
420 | };
421 | /* End PBXSourcesBuildPhase section */
422 |
423 | /* Begin PBXTargetDependency section */
424 | E950DDBE200211B3002F56AE /* PBXTargetDependency */ = {
425 | isa = PBXTargetDependency;
426 | target = E950DDB2200211B3002F56AE /* ACBAVPlayer */;
427 | targetProxy = E950DDBD200211B3002F56AE /* PBXContainerItemProxy */;
428 | };
429 | E950DDC0200211B3002F56AE /* PBXTargetDependency */ = {
430 | isa = PBXTargetDependency;
431 | target = E99BE14A1F3D7D09005EF6B1 /* ACBAVPlayerExtension */;
432 | targetProxy = E950DDBF200211B3002F56AE /* PBXContainerItemProxy */;
433 | };
434 | E950DDC7200211B3002F56AE /* PBXTargetDependency */ = {
435 | isa = PBXTargetDependency;
436 | target = E950DDB2200211B3002F56AE /* ACBAVPlayer */;
437 | targetProxy = E950DDC6200211B3002F56AE /* PBXContainerItemProxy */;
438 | };
439 | /* End PBXTargetDependency section */
440 |
441 | /* Begin PBXVariantGroup section */
442 | E99BE1671F3D7DBC005EF6B1 /* LaunchScreen.storyboard */ = {
443 | isa = PBXVariantGroup;
444 | children = (
445 | E99BE1681F3D7DBC005EF6B1 /* Base */,
446 | );
447 | name = LaunchScreen.storyboard;
448 | sourceTree = "";
449 | };
450 | E99BE1691F3D7DBC005EF6B1 /* Main.storyboard */ = {
451 | isa = PBXVariantGroup;
452 | children = (
453 | E99BE16A1F3D7DBC005EF6B1 /* Base */,
454 | );
455 | name = Main.storyboard;
456 | sourceTree = "";
457 | };
458 | /* End PBXVariantGroup section */
459 |
460 | /* Begin XCBuildConfiguration section */
461 | E950DDCB200211B3002F56AE /* Debug */ = {
462 | isa = XCBuildConfiguration;
463 | buildSettings = {
464 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
465 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
466 | CLANG_WARN_COMMA = YES;
467 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
468 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
469 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
470 | CLANG_WARN_STRICT_PROTOTYPES = YES;
471 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
472 | CODE_SIGN_IDENTITY = "";
473 | CODE_SIGN_STYLE = Automatic;
474 | CURRENT_PROJECT_VERSION = 1;
475 | DEFINES_MODULE = YES;
476 | DEVELOPMENT_TEAM = "";
477 | DYLIB_COMPATIBILITY_VERSION = 1;
478 | DYLIB_CURRENT_VERSION = 1;
479 | DYLIB_INSTALL_NAME_BASE = "@rpath";
480 | ENABLE_MODULE_VERIFIER = YES;
481 | GCC_C_LANGUAGE_STANDARD = gnu11;
482 | INFOPLIST_FILE = ACBAVPlayer/Info.plist;
483 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
484 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
485 | LD_RUNPATH_SEARCH_PATHS = (
486 | "$(inherited)",
487 | "@executable_path/Frameworks",
488 | "@loader_path/Frameworks",
489 | );
490 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
491 | OTHER_LDFLAGS = "-ObjC";
492 | PRODUCT_BUNDLE_IDENTIFIER = com.akhil.ACBAVPlayer;
493 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
494 | SKIP_INSTALL = YES;
495 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
496 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
497 | SWIFT_VERSION = 4.0;
498 | TARGETED_DEVICE_FAMILY = "1,2";
499 | VERSIONING_SYSTEM = "apple-generic";
500 | VERSION_INFO_PREFIX = "";
501 | };
502 | name = Debug;
503 | };
504 | E950DDCC200211B3002F56AE /* Release */ = {
505 | isa = XCBuildConfiguration;
506 | buildSettings = {
507 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
508 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
509 | CLANG_WARN_COMMA = YES;
510 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
511 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
512 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
513 | CLANG_WARN_STRICT_PROTOTYPES = YES;
514 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
515 | CODE_SIGN_IDENTITY = "";
516 | CODE_SIGN_STYLE = Automatic;
517 | CURRENT_PROJECT_VERSION = 1;
518 | DEFINES_MODULE = YES;
519 | DEVELOPMENT_TEAM = "";
520 | DYLIB_COMPATIBILITY_VERSION = 1;
521 | DYLIB_CURRENT_VERSION = 1;
522 | DYLIB_INSTALL_NAME_BASE = "@rpath";
523 | ENABLE_MODULE_VERIFIER = YES;
524 | GCC_C_LANGUAGE_STANDARD = gnu11;
525 | INFOPLIST_FILE = ACBAVPlayer/Info.plist;
526 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
527 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
528 | LD_RUNPATH_SEARCH_PATHS = (
529 | "$(inherited)",
530 | "@executable_path/Frameworks",
531 | "@loader_path/Frameworks",
532 | );
533 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
534 | OTHER_LDFLAGS = "-ObjC";
535 | PRODUCT_BUNDLE_IDENTIFIER = com.akhil.ACBAVPlayer;
536 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
537 | SKIP_INSTALL = YES;
538 | SWIFT_COMPILATION_MODE = wholemodule;
539 | SWIFT_OPTIMIZATION_LEVEL = "-O";
540 | SWIFT_VERSION = 4.0;
541 | TARGETED_DEVICE_FAMILY = "1,2";
542 | VERSIONING_SYSTEM = "apple-generic";
543 | VERSION_INFO_PREFIX = "";
544 | };
545 | name = Release;
546 | };
547 | E950DDCD200211B3002F56AE /* Debug */ = {
548 | isa = XCBuildConfiguration;
549 | buildSettings = {
550 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
551 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
552 | CLANG_WARN_COMMA = YES;
553 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
554 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
555 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
556 | CLANG_WARN_STRICT_PROTOTYPES = YES;
557 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
558 | CODE_SIGN_IDENTITY = "iPhone Developer";
559 | CODE_SIGN_STYLE = Automatic;
560 | GCC_C_LANGUAGE_STANDARD = gnu11;
561 | INFOPLIST_FILE = ACBAVPlayerTests/Info.plist;
562 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
563 | LD_RUNPATH_SEARCH_PATHS = (
564 | "$(inherited)",
565 | "@executable_path/Frameworks",
566 | "@loader_path/Frameworks",
567 | );
568 | PRODUCT_BUNDLE_IDENTIFIER = com.akhil.ACBAVPlayerTests;
569 | PRODUCT_NAME = "$(TARGET_NAME)";
570 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
571 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
572 | SWIFT_VERSION = 5.0;
573 | TARGETED_DEVICE_FAMILY = "1,2";
574 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ACBAVPlayerExtension.app/ACBAVPlayerExtension";
575 | };
576 | name = Debug;
577 | };
578 | E950DDCE200211B3002F56AE /* Release */ = {
579 | isa = XCBuildConfiguration;
580 | buildSettings = {
581 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
582 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
583 | CLANG_WARN_COMMA = YES;
584 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
585 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
586 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
587 | CLANG_WARN_STRICT_PROTOTYPES = YES;
588 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
589 | CODE_SIGN_IDENTITY = "iPhone Developer";
590 | CODE_SIGN_STYLE = Automatic;
591 | GCC_C_LANGUAGE_STANDARD = gnu11;
592 | INFOPLIST_FILE = ACBAVPlayerTests/Info.plist;
593 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
594 | LD_RUNPATH_SEARCH_PATHS = (
595 | "$(inherited)",
596 | "@executable_path/Frameworks",
597 | "@loader_path/Frameworks",
598 | );
599 | PRODUCT_BUNDLE_IDENTIFIER = com.akhil.ACBAVPlayerTests;
600 | PRODUCT_NAME = "$(TARGET_NAME)";
601 | SWIFT_COMPILATION_MODE = wholemodule;
602 | SWIFT_OPTIMIZATION_LEVEL = "-O";
603 | SWIFT_VERSION = 5.0;
604 | TARGETED_DEVICE_FAMILY = "1,2";
605 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ACBAVPlayerExtension.app/ACBAVPlayerExtension";
606 | };
607 | name = Release;
608 | };
609 | E99BE1601F3D7D09005EF6B1 /* Debug */ = {
610 | isa = XCBuildConfiguration;
611 | buildSettings = {
612 | ALWAYS_SEARCH_USER_PATHS = NO;
613 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
614 | CLANG_ANALYZER_NONNULL = YES;
615 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
616 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
617 | CLANG_CXX_LIBRARY = "libc++";
618 | CLANG_ENABLE_MODULES = YES;
619 | CLANG_ENABLE_OBJC_ARC = YES;
620 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
621 | CLANG_WARN_BOOL_CONVERSION = YES;
622 | CLANG_WARN_COMMA = YES;
623 | CLANG_WARN_CONSTANT_CONVERSION = YES;
624 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
625 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
626 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
627 | CLANG_WARN_EMPTY_BODY = YES;
628 | CLANG_WARN_ENUM_CONVERSION = YES;
629 | CLANG_WARN_INFINITE_RECURSION = YES;
630 | CLANG_WARN_INT_CONVERSION = YES;
631 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
632 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
633 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
634 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
635 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
636 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
637 | CLANG_WARN_STRICT_PROTOTYPES = YES;
638 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
639 | CLANG_WARN_UNREACHABLE_CODE = YES;
640 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
641 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
642 | COPY_PHASE_STRIP = NO;
643 | DEBUG_INFORMATION_FORMAT = dwarf;
644 | ENABLE_STRICT_OBJC_MSGSEND = YES;
645 | ENABLE_TESTABILITY = YES;
646 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
647 | GCC_C_LANGUAGE_STANDARD = gnu99;
648 | GCC_DYNAMIC_NO_PIC = NO;
649 | GCC_NO_COMMON_BLOCKS = YES;
650 | GCC_OPTIMIZATION_LEVEL = 0;
651 | GCC_PREPROCESSOR_DEFINITIONS = (
652 | "DEBUG=1",
653 | "$(inherited)",
654 | );
655 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
656 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
657 | GCC_WARN_UNDECLARED_SELECTOR = YES;
658 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
659 | GCC_WARN_UNUSED_FUNCTION = YES;
660 | GCC_WARN_UNUSED_VARIABLE = YES;
661 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
662 | MTL_ENABLE_DEBUG_INFO = YES;
663 | ONLY_ACTIVE_ARCH = YES;
664 | SDKROOT = iphoneos;
665 | TARGETED_DEVICE_FAMILY = "1,2";
666 | };
667 | name = Debug;
668 | };
669 | E99BE1611F3D7D09005EF6B1 /* Release */ = {
670 | isa = XCBuildConfiguration;
671 | buildSettings = {
672 | ALWAYS_SEARCH_USER_PATHS = NO;
673 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
674 | CLANG_ANALYZER_NONNULL = YES;
675 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
676 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
677 | CLANG_CXX_LIBRARY = "libc++";
678 | CLANG_ENABLE_MODULES = YES;
679 | CLANG_ENABLE_OBJC_ARC = YES;
680 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
681 | CLANG_WARN_BOOL_CONVERSION = YES;
682 | CLANG_WARN_COMMA = YES;
683 | CLANG_WARN_CONSTANT_CONVERSION = YES;
684 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
685 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
686 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
687 | CLANG_WARN_EMPTY_BODY = YES;
688 | CLANG_WARN_ENUM_CONVERSION = YES;
689 | CLANG_WARN_INFINITE_RECURSION = YES;
690 | CLANG_WARN_INT_CONVERSION = YES;
691 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
692 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
693 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
694 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
695 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
696 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
697 | CLANG_WARN_STRICT_PROTOTYPES = YES;
698 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
699 | CLANG_WARN_UNREACHABLE_CODE = YES;
700 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
701 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
702 | COPY_PHASE_STRIP = NO;
703 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
704 | ENABLE_NS_ASSERTIONS = NO;
705 | ENABLE_STRICT_OBJC_MSGSEND = YES;
706 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
707 | GCC_C_LANGUAGE_STANDARD = gnu99;
708 | GCC_NO_COMMON_BLOCKS = YES;
709 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
710 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
711 | GCC_WARN_UNDECLARED_SELECTOR = YES;
712 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
713 | GCC_WARN_UNUSED_FUNCTION = YES;
714 | GCC_WARN_UNUSED_VARIABLE = YES;
715 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
716 | MTL_ENABLE_DEBUG_INFO = NO;
717 | SDKROOT = iphoneos;
718 | SWIFT_COMPILATION_MODE = wholemodule;
719 | TARGETED_DEVICE_FAMILY = "1,2";
720 | VALIDATE_PRODUCT = YES;
721 | };
722 | name = Release;
723 | };
724 | E99BE1631F3D7D09005EF6B1 /* Debug */ = {
725 | isa = XCBuildConfiguration;
726 | buildSettings = {
727 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
728 | CODE_SIGN_IDENTITY = "iPhone Developer";
729 | DEVELOPMENT_TEAM = "";
730 | INFOPLIST_FILE = ACBAVPlayerExtension/Info.plist;
731 | LD_RUNPATH_SEARCH_PATHS = (
732 | "$(inherited)",
733 | "@executable_path/Frameworks",
734 | );
735 | PRODUCT_BUNDLE_IDENTIFIER = com.akhil.ACBAVPlayerExtension;
736 | PRODUCT_NAME = "$(TARGET_NAME)";
737 | };
738 | name = Debug;
739 | };
740 | E99BE1641F3D7D09005EF6B1 /* Release */ = {
741 | isa = XCBuildConfiguration;
742 | buildSettings = {
743 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
744 | CODE_SIGN_IDENTITY = "iPhone Developer";
745 | DEVELOPMENT_TEAM = "";
746 | INFOPLIST_FILE = ACBAVPlayerExtension/Info.plist;
747 | LD_RUNPATH_SEARCH_PATHS = (
748 | "$(inherited)",
749 | "@executable_path/Frameworks",
750 | );
751 | PRODUCT_BUNDLE_IDENTIFIER = com.akhil.ACBAVPlayerExtension;
752 | PRODUCT_NAME = "$(TARGET_NAME)";
753 | };
754 | name = Release;
755 | };
756 | /* End XCBuildConfiguration section */
757 |
758 | /* Begin XCConfigurationList section */
759 | E950DDCF200211B3002F56AE /* Build configuration list for PBXNativeTarget "ACBAVPlayer" */ = {
760 | isa = XCConfigurationList;
761 | buildConfigurations = (
762 | E950DDCB200211B3002F56AE /* Debug */,
763 | E950DDCC200211B3002F56AE /* Release */,
764 | );
765 | defaultConfigurationIsVisible = 0;
766 | defaultConfigurationName = Release;
767 | };
768 | E950DDD0200211B3002F56AE /* Build configuration list for PBXNativeTarget "ACBAVPlayerTests" */ = {
769 | isa = XCConfigurationList;
770 | buildConfigurations = (
771 | E950DDCD200211B3002F56AE /* Debug */,
772 | E950DDCE200211B3002F56AE /* Release */,
773 | );
774 | defaultConfigurationIsVisible = 0;
775 | defaultConfigurationName = Release;
776 | };
777 | E99BE1461F3D7D09005EF6B1 /* Build configuration list for PBXProject "ACBAVPlayerExtension" */ = {
778 | isa = XCConfigurationList;
779 | buildConfigurations = (
780 | E99BE1601F3D7D09005EF6B1 /* Debug */,
781 | E99BE1611F3D7D09005EF6B1 /* Release */,
782 | );
783 | defaultConfigurationIsVisible = 0;
784 | defaultConfigurationName = Release;
785 | };
786 | E99BE1621F3D7D09005EF6B1 /* Build configuration list for PBXNativeTarget "ACBAVPlayerExtension" */ = {
787 | isa = XCConfigurationList;
788 | buildConfigurations = (
789 | E99BE1631F3D7D09005EF6B1 /* Debug */,
790 | E99BE1641F3D7D09005EF6B1 /* Release */,
791 | );
792 | defaultConfigurationIsVisible = 0;
793 | defaultConfigurationName = Release;
794 | };
795 | /* End XCConfigurationList section */
796 | };
797 | rootObject = E99BE1431F3D7D09005EF6B1 /* Project object */;
798 | }
799 |
--------------------------------------------------------------------------------