react-native-audio-api 0.5.5 → 0.6.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/RNAudioAPI.podspec +1 -1
  2. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +0 -20
  3. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +0 -2
  4. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +13 -0
  5. package/android/src/main/java/com/swmansion/audioapi/AudioManagerModule.kt +59 -0
  6. package/android/src/oldarch/NativeAudioManagerModuleSpec.java +99 -0
  7. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +30 -6
  8. package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.h +70 -0
  9. package/common/cpp/audioapi/core/AudioContext.cpp +1 -12
  10. package/common/cpp/audioapi/core/AudioContext.h +0 -1
  11. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +117 -0
  12. package/common/cpp/audioapi/core/OfflineAudioContext.h +40 -0
  13. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +3 -3
  14. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +28 -2
  15. package/common/cpp/audioapi/core/utils/AudioNodeDestructor.cpp +53 -0
  16. package/common/cpp/audioapi/core/utils/AudioNodeDestructor.h +33 -0
  17. package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +13 -10
  18. package/common/cpp/audioapi/core/utils/AudioNodeManager.h +3 -0
  19. package/common/cpp/audioapi/libs/signalsmith-stretch/fft-accelerate.h +326 -0
  20. package/common/cpp/audioapi/libs/signalsmith-stretch/fft.h +1257 -413
  21. package/common/cpp/audioapi/libs/signalsmith-stretch/signalsmith-stretch.h +398 -232
  22. package/common/cpp/audioapi/libs/signalsmith-stretch/stft.h +625 -0
  23. package/ios/audioapi/ios/AudioAPIModule.mm +2 -3
  24. package/ios/audioapi/ios/AudioManagerModule.h +18 -0
  25. package/ios/audioapi/ios/AudioManagerModule.mm +92 -0
  26. package/ios/audioapi/ios/core/AudioPlayer.h +4 -12
  27. package/ios/audioapi/ios/core/AudioPlayer.m +26 -108
  28. package/ios/audioapi/ios/core/IOSAudioPlayer.h +1 -3
  29. package/ios/audioapi/ios/core/IOSAudioPlayer.mm +4 -28
  30. package/ios/audioapi/ios/system/AudioEngine.h +23 -0
  31. package/ios/audioapi/ios/system/AudioEngine.mm +137 -0
  32. package/ios/audioapi/ios/system/AudioSessionManager.h +22 -0
  33. package/ios/audioapi/ios/system/AudioSessionManager.mm +183 -0
  34. package/ios/audioapi/ios/system/LockScreenManager.h +23 -0
  35. package/ios/audioapi/ios/system/LockScreenManager.mm +299 -0
  36. package/ios/audioapi/ios/system/NotificationManager.h +16 -0
  37. package/ios/audioapi/ios/system/NotificationManager.mm +151 -0
  38. package/lib/module/api.js +3 -1
  39. package/lib/module/api.js.map +1 -1
  40. package/lib/module/api.web.js +1 -0
  41. package/lib/module/api.web.js.map +1 -1
  42. package/lib/module/core/AudioContext.js +2 -1
  43. package/lib/module/core/AudioContext.js.map +1 -1
  44. package/lib/module/core/OfflineAudioContext.js +57 -0
  45. package/lib/module/core/OfflineAudioContext.js.map +1 -0
  46. package/lib/module/specs/NativeAudioManagerModule.js +31 -0
  47. package/lib/module/specs/NativeAudioManagerModule.js.map +1 -0
  48. package/lib/module/specs/index.js +6 -0
  49. package/lib/module/specs/index.js.map +1 -0
  50. package/lib/module/system/AudioManager.js +66 -0
  51. package/lib/module/system/AudioManager.js.map +1 -0
  52. package/lib/module/system/index.js +4 -0
  53. package/lib/module/system/index.js.map +1 -0
  54. package/lib/module/system/types.js +2 -0
  55. package/lib/module/system/types.js.map +1 -0
  56. package/lib/module/web-core/OfflineAudioContext.js +90 -0
  57. package/lib/module/web-core/OfflineAudioContext.js.map +1 -0
  58. package/lib/typescript/api.d.ts +4 -1
  59. package/lib/typescript/api.d.ts.map +1 -1
  60. package/lib/typescript/api.web.d.ts +1 -0
  61. package/lib/typescript/api.web.d.ts.map +1 -1
  62. package/lib/typescript/core/AudioContext.d.ts.map +1 -1
  63. package/lib/typescript/core/OfflineAudioContext.d.ts +14 -0
  64. package/lib/typescript/core/OfflineAudioContext.d.ts.map +1 -0
  65. package/lib/typescript/interfaces.d.ts +6 -0
  66. package/lib/typescript/interfaces.d.ts.map +1 -1
  67. package/lib/typescript/specs/NativeAudioManagerModule.d.ts +13 -0
  68. package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +1 -0
  69. package/lib/typescript/specs/index.d.ts +4 -0
  70. package/lib/typescript/specs/index.d.ts.map +1 -0
  71. package/lib/typescript/system/AudioManager.d.ts +12 -0
  72. package/lib/typescript/system/AudioManager.d.ts.map +1 -0
  73. package/lib/typescript/system/index.d.ts +2 -0
  74. package/lib/typescript/system/index.d.ts.map +1 -0
  75. package/lib/typescript/system/types.d.ts +28 -0
  76. package/lib/typescript/system/types.d.ts.map +1 -0
  77. package/lib/typescript/types.d.ts +5 -0
  78. package/lib/typescript/types.d.ts.map +1 -1
  79. package/lib/typescript/web-core/OfflineAudioContext.d.ts +34 -0
  80. package/lib/typescript/web-core/OfflineAudioContext.d.ts.map +1 -0
  81. package/package.json +2 -2
  82. package/src/api.ts +12 -2
  83. package/src/api.web.ts +1 -0
  84. package/src/core/AudioContext.ts +6 -1
  85. package/src/core/OfflineAudioContext.ts +94 -0
  86. package/src/interfaces.ts +11 -0
  87. package/src/specs/NativeAudioManagerModule.ts +51 -0
  88. package/src/specs/index.ts +6 -0
  89. package/src/system/AudioManager.ts +122 -0
  90. package/src/system/index.ts +1 -0
  91. package/src/system/types.ts +68 -0
  92. package/src/types.ts +6 -0
  93. package/src/web-core/OfflineAudioContext.tsx +163 -0
  94. package/common/cpp/audioapi/libs/signalsmith-stretch/delay.h +0 -715
  95. package/common/cpp/audioapi/libs/signalsmith-stretch/perf.h +0 -82
  96. package/common/cpp/audioapi/libs/signalsmith-stretch/spectral.h +0 -493
@@ -0,0 +1,92 @@
1
+ #import <audioapi/ios/AudioManagerModule.h>
2
+
3
+ #import <audioapi/ios/system/AudioEngine.h>
4
+ #import <audioapi/ios/system/AudioSessionManager.h>
5
+ #import <audioapi/ios/system/LockScreenManager.h>
6
+ #import <audioapi/ios/system/NotificationManager.h>
7
+
8
+ @implementation AudioManagerModule
9
+
10
+ RCT_EXPORT_MODULE(AudioManagerModule);
11
+
12
+ - (id)init
13
+ {
14
+ if (self == [super init]) {
15
+ self.audioEngine = [AudioEngine sharedInstance];
16
+ self.audioSessionManager = [AudioSessionManager sharedInstance];
17
+ self.notificationManager = [NotificationManager sharedInstance];
18
+ self.lockScreenManager = [LockScreenManager sharedInstanceWithAudioManagerModule:self];
19
+ }
20
+
21
+ return self;
22
+ }
23
+
24
+ - (void)cleanup
25
+ {
26
+ [self.audioEngine cleanup];
27
+ [self.notificationManager cleanup];
28
+ [self.audioSessionManager cleanup];
29
+ [self.lockScreenManager cleanup];
30
+ }
31
+
32
+ - (void)dealloc
33
+ {
34
+ [self cleanup];
35
+ }
36
+
37
+ RCT_EXPORT_METHOD(setLockScreenInfo : (NSDictionary *)info)
38
+ {
39
+ [self.lockScreenManager setLockScreenInfo:info];
40
+ }
41
+
42
+ RCT_EXPORT_METHOD(resetLockScreenInfo)
43
+ {
44
+ [self.lockScreenManager resetLockScreenInfo];
45
+ }
46
+
47
+ RCT_EXPORT_METHOD(enableRemoteCommand : (NSString *)name enabled : (BOOL)enabled)
48
+ {
49
+ [self.lockScreenManager enableRemoteCommand:name enabled:enabled];
50
+ }
51
+
52
+ RCT_EXPORT_METHOD(setAudioSessionOptions : (NSString *)category mode : (NSString *)mode options : (NSArray *)
53
+ options active : (BOOL)active)
54
+ {
55
+ NSError *error = nil;
56
+
57
+ if (active) {
58
+ [self.audioSessionManager setAudioSessionOptions:category mode:mode options:options];
59
+ } else {
60
+ [self.audioSessionManager setActive:false error:&error];
61
+ }
62
+ }
63
+
64
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getDevicePreferredSampleRate)
65
+ {
66
+ return [self.audioSessionManager getDevicePreferredSampleRate];
67
+ }
68
+
69
+ - (NSArray<NSString *> *)supportedEvents
70
+ {
71
+ return @[
72
+ @"onRemotePlay",
73
+ @"onRemotePause",
74
+ @"onRemoteStop",
75
+ @"onRemoteTogglePlayPause",
76
+ @"onRemoteChangePlaybackRate",
77
+ @"onRemoteNextTrack",
78
+ @"onRemotePreviousTrack",
79
+ @"onRemoteSkipForward",
80
+ @"onRemoteSkipBackward",
81
+ @"onRemoteSeekForward",
82
+ @"onRemoteSeekBackward",
83
+ @"onRemoteChangePlaybackPosition"
84
+ ];
85
+ }
86
+
87
+ - (void)sendEventWithValue:(NSString *)event withValue:(NSString *)value
88
+ {
89
+ [self sendEventWithName:@"AudioManagerModule" body:@{@"name" : event, @"value" : value}];
90
+ }
91
+
92
+ @end
@@ -7,22 +7,18 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
7
7
 
8
8
  @interface AudioPlayer : NSObject
9
9
 
10
- @property (nonatomic, strong) AVAudioEngine *audioEngine;
11
- @property (nonatomic, weak) AVAudioSession *audioSession;
12
- @property (nonatomic, weak) NSNotificationCenter *notificationCenter;
13
10
  @property (nonatomic, strong) AVAudioFormat *format;
14
11
  @property (nonatomic, strong) AVAudioSourceNode *sourceNode;
15
12
  @property (nonatomic, copy) RenderAudioBlock renderAudio;
16
13
  @property (nonatomic, assign) float sampleRate;
17
14
  @property (nonatomic, assign) int channelCount;
18
15
  @property (nonatomic, assign) bool isRunning;
16
+ @property (nonatomic, strong) NSString *sourceNodeId;
19
17
  @property (nonatomic, strong) AVAudioSourceNodeRenderBlock renderBlock;
20
18
 
21
- - (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio channelCount:(int)channelCount;
22
-
23
- - (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio
24
- sampleRate:(float)sampleRate
25
- channelCount:(int)channelCount;
19
+ - (instancetype)initWithRenderAudio:(RenderAudioBlock)renderAudio
20
+ sampleRate:(float)sampleRate
21
+ channelCount:(int)channelCount;
26
22
 
27
23
  - (float)getSampleRate;
28
24
 
@@ -36,8 +32,4 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
36
32
 
37
33
  - (void)cleanup;
38
34
 
39
- - (void)setupAndInitAudioSession;
40
-
41
- - (void)connectAudioEngine;
42
-
43
35
  @end
@@ -1,52 +1,17 @@
1
1
  #import <audioapi/ios/core/AudioPlayer.h>
2
+ #import <audioapi/ios/system/AudioEngine.h>
2
3
 
3
4
  @implementation AudioPlayer
4
5
 
5
- - (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio channelCount:(int)channelCount
6
+ - (instancetype)initWithRenderAudio:(RenderAudioBlock)renderAudio
7
+ sampleRate:(float)sampleRate
8
+ channelCount:(int)channelCount
6
9
  {
7
10
  if (self = [super init]) {
8
- self.renderAudio = [renderAudio copy];
9
- self.audioEngine = [[AVAudioEngine alloc] init];
10
- self.audioEngine.mainMixerNode.outputVolume = 1;
11
- self.isRunning = true;
12
-
13
- [self setupAndInitAudioSession];
11
+ self.sampleRate = sampleRate;
14
12
 
15
- self.sampleRate = [self.audioSession sampleRate];
16
13
  self.channelCount = channelCount;
17
-
18
- __weak typeof(self) weakSelf = self;
19
- self.renderBlock = ^OSStatus(
20
- BOOL *isSilence, const AudioTimeStamp *timestamp, AVAudioFrameCount frameCount, AudioBufferList *outputData) {
21
- if (outputData->mNumberBuffers != weakSelf.channelCount) {
22
- return kAudioServicesBadPropertySizeError;
23
- }
24
-
25
- weakSelf.renderAudio(outputData, frameCount);
26
- return kAudioServicesNoError;
27
- };
28
-
29
- _format = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:self.sampleRate channels:self.channelCount];
30
- _sourceNode = [[AVAudioSourceNode alloc] initWithFormat:self.format renderBlock:self.renderBlock];
31
- }
32
-
33
- return self;
34
- }
35
-
36
- - (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio
37
- sampleRate:(float)sampleRate
38
- channelCount:(int)channelCount
39
- {
40
- if (self = [super init]) {
41
14
  self.renderAudio = [renderAudio copy];
42
- self.audioEngine = [[AVAudioEngine alloc] init];
43
- self.audioEngine.mainMixerNode.outputVolume = 1;
44
- self.isRunning = true;
45
-
46
- [self setupAndInitAudioSession];
47
-
48
- self.sampleRate = sampleRate;
49
- self.channelCount = channelCount;
50
15
 
51
16
  __weak typeof(self) weakSelf = self;
52
17
  self.renderBlock = ^OSStatus(
@@ -73,96 +38,49 @@
73
38
 
74
39
  - (void)start
75
40
  {
41
+ NSLog(@"[AudioPlayer] start");
42
+ AudioEngine *audioEngine = [AudioEngine sharedInstance];
76
43
  self.isRunning = true;
77
- [self connectAudioEngine];
44
+ self.sourceNodeId = [audioEngine attachSourceNode:self.sourceNode format:self.format];
78
45
  }
79
46
 
80
47
  - (void)stop
81
48
  {
82
- self.isRunning = false;
83
- [self.audioEngine detachNode:self.sourceNode];
84
-
85
- if (self.audioEngine.isRunning) {
86
- [self.audioEngine stop];
49
+ NSLog(@"[AudioPlayer] stop");
50
+ if (!self.isRunning) {
51
+ return;
87
52
  }
88
53
 
89
- NSError *error = nil;
90
- [self.audioSession setActive:false error:&error];
91
-
92
- if (error != nil) {
93
- NSLog(@"Error while deactivating audio session: %@", [error debugDescription]);
94
- }
54
+ AudioEngine *audioEngine = [AudioEngine sharedInstance];
55
+ self.isRunning = false;
56
+ [audioEngine detachSourceNodeWithId:self.sourceNodeId];
57
+ self.sourceNodeId = nil;
95
58
  }
96
59
 
97
60
  - (void)suspend
98
61
  {
99
- [self.audioEngine pause];
62
+ NSLog(@"[AudioPlayer] suspend");
63
+ if (!self.isRunning) {
64
+ return;
65
+ }
66
+
67
+ AudioEngine *audioEngine = [AudioEngine sharedInstance];
100
68
  self.isRunning = false;
69
+ [audioEngine detachSourceNodeWithId:self.sourceNodeId];
70
+ self.sourceNodeId = nil;
101
71
  }
102
72
 
103
73
  - (void)resume
104
74
  {
75
+ NSLog(@"[AudioPlayer] resume");
76
+ AudioEngine *audioEngine = [AudioEngine sharedInstance];
105
77
  self.isRunning = true;
106
- [self setupAndInitAudioSession];
107
- [self connectAudioEngine];
78
+ self.sourceNodeId = [audioEngine attachSourceNode:self.sourceNode format:self.format];
108
79
  }
109
80
 
110
81
  - (void)cleanup
111
82
  {
112
- self.audioEngine = nil;
113
- self.audioSession = nil;
114
83
  self.renderAudio = nil;
115
84
  }
116
85
 
117
- - (void)setupAndInitAudioSession
118
- {
119
- NSError *error = nil;
120
-
121
- if (!self.audioSession) {
122
- self.audioSession = [AVAudioSession sharedInstance];
123
- }
124
-
125
- [self.audioSession setCategory:AVAudioSessionCategoryPlayback
126
- mode:AVAudioSessionModeDefault
127
- options:AVAudioSessionCategoryOptionDuckOthers | AVAudioSessionCategoryOptionAllowAirPlay
128
- error:&error];
129
-
130
- if (error != nil) {
131
- NSLog(@"Error while configuring audio session: %@", [error debugDescription]);
132
- return;
133
- }
134
-
135
- [self.audioSession setPreferredIOBufferDuration:0.022 error:&error];
136
-
137
- if (error != nil) {
138
- NSLog(@"Error while setting buffer size in audio session: %@", [error debugDescription]);
139
- return;
140
- }
141
-
142
- [self.audioSession setActive:true error:&error];
143
-
144
- if (error != nil) {
145
- NSLog(@"Error while activating audio session: %@", [error debugDescription]);
146
- return;
147
- }
148
- }
149
-
150
- - (void)connectAudioEngine
151
- {
152
- if ([self.audioEngine isRunning]) {
153
- return;
154
- }
155
-
156
- [self.audioEngine attachNode:self.sourceNode];
157
- [self.audioEngine connect:self.sourceNode to:self.audioEngine.mainMixerNode format:self.format];
158
-
159
- if (![self.audioEngine isRunning]) {
160
- NSError *error = nil;
161
-
162
- if (![self.audioEngine startAndReturnError:&error]) {
163
- NSLog(@"Error starting audio engine: %@", [error debugDescription]);
164
- }
165
- }
166
- }
167
-
168
86
  @end
@@ -10,8 +10,8 @@ typedef struct objc_object AudioPlayer;
10
10
 
11
11
  namespace audioapi {
12
12
 
13
- class AudioContext;
14
13
  class AudioBus;
14
+ class AudioContext;
15
15
 
16
16
  class IOSAudioPlayer {
17
17
  protected:
@@ -21,8 +21,6 @@ class IOSAudioPlayer {
21
21
  int channelCount_;
22
22
 
23
23
  public:
24
- explicit IOSAudioPlayer(
25
- const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio);
26
24
  IOSAudioPlayer(
27
25
  const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio,
28
26
  float sampleRate);
@@ -8,31 +8,6 @@
8
8
 
9
9
  namespace audioapi {
10
10
 
11
- IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio)
12
- : channelCount_(2), renderAudio_(renderAudio), audioBus_(0)
13
- {
14
- RenderAudioBlock renderAudioBlock = ^(AudioBufferList *outputData, int numFrames) {
15
- int processedFrames = 0;
16
-
17
- while (processedFrames < numFrames) {
18
- int framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
19
- renderAudio_(audioBus_, framesToProcess);
20
-
21
- for (int channel = 0; channel < channelCount_; channel += 1) {
22
- float *outputChannel = (float *)outputData->mBuffers[channel].mData;
23
- auto *inputChannel = audioBus_->getChannel(channel)->getData();
24
-
25
- memcpy(outputChannel + processedFrames, inputChannel, framesToProcess * sizeof(float));
26
- }
27
-
28
- processedFrames += framesToProcess;
29
- }
30
- };
31
-
32
- audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudioBlock:renderAudioBlock channelCount:channelCount_];
33
- audioBus_ = std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, getSampleRate());
34
- }
35
-
36
11
  IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio, float sampleRate)
37
12
  : channelCount_(2), renderAudio_(renderAudio), audioBus_(0)
38
13
  {
@@ -54,9 +29,10 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus
54
29
  }
55
30
  };
56
31
 
57
- audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudioBlock:renderAudioBlock
58
- sampleRate:sampleRate
59
- channelCount:channelCount_];
32
+ audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudio:renderAudioBlock
33
+ sampleRate:sampleRate
34
+ channelCount:channelCount_];
35
+
60
36
  audioBus_ = std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, getSampleRate());
61
37
  }
62
38
 
@@ -0,0 +1,23 @@
1
+ #pragma once
2
+
3
+ #import <AVFoundation/AVFoundation.h>
4
+ #import <Foundation/Foundation.h>
5
+
6
+ @interface AudioEngine : NSObject
7
+
8
+ @property (nonatomic, strong) AVAudioEngine *audioEngine;
9
+ @property (nonatomic, strong) NSMutableDictionary *sourceNodes;
10
+ @property (nonatomic, strong) NSMutableDictionary *sourceFormats;
11
+
12
+ + (instancetype)sharedInstance;
13
+ - (void)cleanup;
14
+
15
+ - (bool)rebuildAudioEngine;
16
+ - (void)startEngine;
17
+ - (void)stopEngine;
18
+ - (bool)isRunning;
19
+
20
+ - (NSString *)attachSourceNode:(AVAudioSourceNode *)sourceNode format:(AVAudioFormat *)format;
21
+ - (void)detachSourceNodeWithId:(NSString *)sourceNodeId;
22
+
23
+ @end
@@ -0,0 +1,137 @@
1
+ #import <audioapi/ios/system/AudioEngine.h>
2
+
3
+ @implementation AudioEngine
4
+
5
+ static AudioEngine *_sharedInstance = nil;
6
+
7
+ + (instancetype)sharedInstance
8
+ {
9
+ static dispatch_once_t onceToken;
10
+ dispatch_once(&onceToken, ^{
11
+ _sharedInstance = [[self alloc] initPrivate];
12
+ });
13
+ return _sharedInstance;
14
+ }
15
+
16
+ - (instancetype)init
17
+ {
18
+ @throw [NSException exceptionWithName:@"Singleton" reason:@"Use +[AudioEngine sharedInstance]" userInfo:nil];
19
+ return nil;
20
+ }
21
+
22
+ - (instancetype)initPrivate
23
+ {
24
+ if (self = [super init]) {
25
+ self.audioEngine = [[AVAudioEngine alloc] init];
26
+ self.audioEngine.mainMixerNode.outputVolume = 1;
27
+ self.sourceNodes = [[NSMutableDictionary alloc] init];
28
+ self.sourceFormats = [[NSMutableDictionary alloc] init];
29
+ }
30
+ return self;
31
+ }
32
+
33
+ - (void)cleanup
34
+ {
35
+ NSLog(@"[AudioEngine] cleanup");
36
+ if ([self.audioEngine isRunning]) {
37
+ [self.audioEngine stop];
38
+ }
39
+
40
+ self.audioEngine = nil;
41
+ self.sourceNodes = nil;
42
+ self.sourceFormats = nil;
43
+ }
44
+
45
+ - (bool)rebuildAudioEngine
46
+ {
47
+ NSError *error = nil;
48
+
49
+ if ([self.audioEngine isRunning]) {
50
+ return true;
51
+ }
52
+
53
+ for (id sourceNodeId in self.sourceNodes) {
54
+ AVAudioSourceNode *sourceNode = [self.sourceNodes valueForKey:sourceNodeId];
55
+ AVAudioFormat *format = [self.sourceFormats valueForKey:sourceNodeId];
56
+
57
+ [self.audioEngine attachNode:sourceNode];
58
+ [self.audioEngine connect:sourceNode to:self.audioEngine.mainMixerNode format:format];
59
+ }
60
+
61
+ if ([self.audioEngine isRunning]) {
62
+ return true;
63
+ }
64
+
65
+ if (![self.audioEngine startAndReturnError:&error]) {
66
+ NSLog(@"Error while rebuilding audio engine: %@", [error debugDescription]);
67
+ return false;
68
+ }
69
+
70
+ return true;
71
+ }
72
+
73
+ - (void)startEngine
74
+ {
75
+ NSLog(@"[AudioEngine] startEngine");
76
+ NSError *error = nil;
77
+
78
+ if ([self.audioEngine isRunning]) {
79
+ return;
80
+ }
81
+
82
+ [self.audioEngine startAndReturnError:&error];
83
+
84
+ if (error != nil) {
85
+ NSLog(@"Error while starting the audio engine: %@", [error debugDescription]);
86
+ }
87
+ }
88
+
89
+ - (void)stopEngine
90
+ {
91
+ NSLog(@"[AudioEngine] stopEngine");
92
+ if (![self.audioEngine isRunning]) {
93
+ return;
94
+ }
95
+
96
+ [self.audioEngine pause];
97
+ }
98
+
99
+ - (bool)isRunning
100
+ {
101
+ return [self.audioEngine isRunning];
102
+ }
103
+
104
+ - (NSString *)attachSourceNode:(AVAudioSourceNode *)sourceNode format:(AVAudioFormat *)format
105
+ {
106
+ NSString *sourceNodeId = [[NSUUID UUID] UUIDString];
107
+ NSLog(@"[AudioEngine] attaching new source node with ID: %@", sourceNodeId);
108
+
109
+ [self.sourceNodes setValue:sourceNode forKey:sourceNodeId];
110
+ [self.sourceFormats setValue:format forKey:sourceNodeId];
111
+
112
+ [self.audioEngine attachNode:sourceNode];
113
+ [self.audioEngine connect:sourceNode to:self.audioEngine.mainMixerNode format:format];
114
+
115
+ if ([self.sourceNodes count] == 1) {
116
+ [self startEngine];
117
+ }
118
+
119
+ return sourceNodeId;
120
+ }
121
+
122
+ - (void)detachSourceNodeWithId:(NSString *)sourceNodeId
123
+ {
124
+ NSLog(@"[AudioEngine] detaching source nde with ID: %@", sourceNodeId);
125
+
126
+ AVAudioSourceNode *sourceNode = [self.sourceNodes valueForKey:sourceNodeId];
127
+ [self.audioEngine detachNode:sourceNode];
128
+
129
+ [self.sourceNodes removeObjectForKey:sourceNodeId];
130
+ [self.sourceFormats removeObjectForKey:sourceNodeId];
131
+
132
+ if ([self.sourceNodes count] == 0) {
133
+ [self stopEngine];
134
+ }
135
+ }
136
+
137
+ @end
@@ -0,0 +1,22 @@
1
+ #pragma once
2
+
3
+ #import <AVFoundation/AVFoundation.h>
4
+ #import <Foundation/Foundation.h>
5
+
6
+ @interface AudioSessionManager : NSObject
7
+
8
+ @property (nonatomic, weak) AVAudioSession *audioSession;
9
+
10
+ @property (nonatomic, assign) AVAudioSessionMode sessionMode;
11
+ @property (nonatomic, assign) AVAudioSessionCategory sessionCategory;
12
+ @property (nonatomic, assign) AVAudioSessionCategoryOptions sessionOptions;
13
+
14
+ + (instancetype)sharedInstance;
15
+ - (void)cleanup;
16
+ - (bool)configureAudioSession;
17
+
18
+ - (NSNumber *)getDevicePreferredSampleRate;
19
+ - (void)setAudioSessionOptions:(NSString *)category mode:(NSString *)mode options:(NSArray *)options;
20
+ - (bool)setActive:(bool)active error:(NSError **)error;
21
+
22
+ @end