react-native-audio-api 0.4.10-rc.1 → 0.4.11

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 (77) hide show
  1. package/android/build.gradle +2 -0
  2. package/android/src/main/cpp/{core/AudioAPIInstaller.cpp → AudioAPIModule.cpp} +12 -11
  3. package/android/src/main/cpp/{core/AudioAPIInstaller.h → AudioAPIModule.h} +9 -11
  4. package/android/src/main/cpp/OnLoad.cpp +2 -2
  5. package/android/src/main/cpp/core/AudioDecoder.cpp +5 -5
  6. package/android/src/main/cpp/core/AudioPlayer.cpp +15 -3
  7. package/android/src/main/cpp/core/AudioPlayer.h +6 -3
  8. package/android/src/main/java/com/swmansion/audioapi/{module/AudioAPIInstaller.kt → AudioAPIModule.kt} +22 -10
  9. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +31 -6
  10. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +37 -0
  11. package/common/cpp/HostObjects/AudioContextHostObject.h +34 -1
  12. package/common/cpp/core/AnalyserNode.cpp +2 -2
  13. package/common/cpp/core/AnalyserNode.h +1 -1
  14. package/common/cpp/core/AudioBuffer.cpp +4 -2
  15. package/common/cpp/core/AudioBuffer.h +1 -1
  16. package/common/cpp/core/AudioBufferSourceNode.cpp +3 -3
  17. package/common/cpp/core/AudioBufferSourceNode.h +3 -3
  18. package/common/cpp/core/AudioContext.cpp +14 -3
  19. package/common/cpp/core/AudioContext.h +3 -1
  20. package/common/cpp/core/AudioDecoder.h +2 -1
  21. package/common/cpp/core/AudioDestinationNode.cpp +3 -3
  22. package/common/cpp/core/AudioDestinationNode.h +3 -3
  23. package/common/cpp/core/AudioNode.cpp +16 -11
  24. package/common/cpp/core/AudioNode.h +6 -6
  25. package/common/cpp/core/AudioScheduledSourceNode.cpp +1 -1
  26. package/common/cpp/core/AudioScheduledSourceNode.h +1 -1
  27. package/common/cpp/core/BiquadFilterNode.cpp +1 -1
  28. package/common/cpp/core/BiquadFilterNode.h +1 -1
  29. package/common/cpp/core/GainNode.cpp +3 -1
  30. package/common/cpp/core/GainNode.h +1 -1
  31. package/common/cpp/core/OscillatorNode.cpp +3 -1
  32. package/common/cpp/core/OscillatorNode.h +1 -1
  33. package/common/cpp/core/StereoPannerNode.cpp +1 -1
  34. package/common/cpp/core/StereoPannerNode.h +1 -1
  35. package/common/cpp/installer/AudioAPIModuleInstaller.cpp +49 -0
  36. package/common/cpp/installer/AudioAPIModuleInstaller.h +49 -0
  37. package/ios/AudioAPIModule.h +1 -1
  38. package/ios/AudioAPIModule.mm +10 -3
  39. package/ios/core/AudioDecoder.mm +2 -3
  40. package/ios/core/AudioPlayer.h +14 -0
  41. package/ios/core/AudioPlayer.m +85 -24
  42. package/ios/core/IOSAudioPlayer.h +6 -4
  43. package/ios/core/IOSAudioPlayer.mm +14 -7
  44. package/lib/module/core/AudioContext.js +7 -1
  45. package/lib/module/core/AudioContext.js.map +1 -1
  46. package/lib/module/index.js +11 -3
  47. package/lib/module/index.js.map +1 -1
  48. package/lib/module/specs/NativeAudioAPIModule.js +5 -0
  49. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -0
  50. package/lib/module/web-core/AudioContext.js +6 -0
  51. package/lib/module/web-core/AudioContext.js.map +1 -1
  52. package/lib/typescript/core/AudioContext.d.ts +2 -0
  53. package/lib/typescript/core/AudioContext.d.ts.map +1 -1
  54. package/lib/typescript/index.d.ts +4 -0
  55. package/lib/typescript/index.d.ts.map +1 -1
  56. package/lib/typescript/interfaces.d.ts +6 -1
  57. package/lib/typescript/interfaces.d.ts.map +1 -1
  58. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +7 -0
  59. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -0
  60. package/lib/typescript/web-core/AudioContext.d.ts +3 -1
  61. package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
  62. package/package.json +9 -7
  63. package/src/core/AudioContext.ts +9 -1
  64. package/src/index.ts +16 -3
  65. package/src/interfaces.ts +7 -1
  66. package/src/specs/NativeAudioAPIModule.ts +7 -0
  67. package/src/web-core/AudioContext.tsx +9 -1
  68. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +0 -26
  69. package/common/cpp/HostObjects/AudioAPIInstallerHostObject.h +0 -56
  70. package/lib/module/specs/global.d.js +0 -4
  71. package/lib/module/specs/global.d.js.map +0 -1
  72. package/lib/module/specs/install.js +0 -18
  73. package/lib/module/specs/install.js.map +0 -1
  74. package/lib/typescript/specs/install.d.ts +0 -7
  75. package/lib/typescript/specs/install.d.ts.map +0 -1
  76. package/src/specs/global.d.ts +0 -12
  77. package/src/specs/install.ts +0 -32
@@ -97,17 +97,19 @@ std::string AudioNode::toString(ChannelInterpretation interpretation) {
97
97
  }
98
98
  }
99
99
 
100
- AudioBus *AudioNode::processAudio(AudioBus *outputBus, int framesToProcess) {
100
+ std::shared_ptr<AudioBus> AudioNode::processAudio(
101
+ std::shared_ptr<AudioBus> outputBus,
102
+ int framesToProcess) {
101
103
  if (!isInitialized_) {
102
104
  return outputBus;
103
105
  }
104
106
 
105
107
  if (isAlreadyProcessed()) {
106
- return audioBus_.get();
108
+ return audioBus_;
107
109
  }
108
110
 
109
111
  // Process inputs and return the bus with the most channels.
110
- AudioBus *processingBus = processInputs(outputBus, framesToProcess);
112
+ auto processingBus = processInputs(outputBus, framesToProcess);
111
113
 
112
114
  // Apply channel count mode.
113
115
  processingBus = applyChannelCountMode(processingBus);
@@ -138,8 +140,10 @@ bool AudioNode::isAlreadyProcessed() {
138
140
  return false;
139
141
  }
140
142
 
141
- AudioBus *AudioNode::processInputs(AudioBus *outputBus, int framesToProcess) {
142
- AudioBus *processingBus = audioBus_.get();
143
+ std::shared_ptr<AudioBus> AudioNode::processInputs(
144
+ const std::shared_ptr<AudioBus> &outputBus,
145
+ int framesToProcess) {
146
+ auto processingBus = audioBus_;
143
147
  processingBus->zero();
144
148
 
145
149
  int maxNumberOfChannels = 0;
@@ -162,28 +166,29 @@ AudioBus *AudioNode::processInputs(AudioBus *outputBus, int framesToProcess) {
162
166
  return processingBus;
163
167
  }
164
168
 
165
- AudioBus *AudioNode::applyChannelCountMode(AudioBus *processingBus) {
169
+ std::shared_ptr<AudioBus> AudioNode::applyChannelCountMode(
170
+ std::shared_ptr<AudioBus> processingBus) {
166
171
  // If the channelCountMode is EXPLICIT, the node should output the number of
167
172
  // channels specified by the channelCount.
168
173
  if (channelCountMode_ == ChannelCountMode::EXPLICIT) {
169
- return audioBus_.get();
174
+ return audioBus_;
170
175
  }
171
176
 
172
177
  // If the channelCountMode is CLAMPED_MAX, the node should output the maximum
173
178
  // number of channels clamped to channelCount.
174
179
  if (channelCountMode_ == ChannelCountMode::CLAMPED_MAX &&
175
180
  processingBus->getNumberOfChannels() >= channelCount_) {
176
- return audioBus_.get();
181
+ return audioBus_;
177
182
  }
178
183
 
179
184
  return processingBus;
180
185
  }
181
186
 
182
- void AudioNode::mixInputsBuses(AudioBus *processingBus) {
187
+ void AudioNode::mixInputsBuses(const std::shared_ptr<AudioBus> &processingBus) {
183
188
  assert(processingBus != nullptr);
184
189
 
185
- for (auto inputBus : inputBuses_) {
186
- processingBus->sum(inputBus, channelInterpretation_);
190
+ for (const auto &inputBus : inputBuses_) {
191
+ processingBus->sum(inputBus.get(), channelInterpretation_);
187
192
  }
188
193
 
189
194
  inputBuses_.clear();
@@ -57,18 +57,18 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
57
57
  std::size_t lastRenderedFrame_{SIZE_MAX};
58
58
 
59
59
  private:
60
- std::vector<AudioBus*> inputBuses_;
60
+ std::vector<std::shared_ptr<AudioBus>> inputBuses_ = {};
61
61
 
62
62
  static std::string toString(ChannelCountMode mode);
63
63
  static std::string toString(ChannelInterpretation interpretation);
64
64
 
65
- AudioBus *processAudio(AudioBus *outputBus, int framesToProcess);
66
- virtual void processNode(AudioBus *processingBus, int framesToProcess) = 0;
65
+ std::shared_ptr<AudioBus> processAudio(std::shared_ptr<AudioBus> outputBus, int framesToProcess);
66
+ virtual void processNode(const std::shared_ptr<AudioBus>&, int) = 0;
67
67
 
68
68
  bool isAlreadyProcessed();
69
- AudioBus *processInputs(AudioBus *outputBus, int framesToProcess);
70
- AudioBus *applyChannelCountMode(AudioBus *processingBus);
71
- void mixInputsBuses(AudioBus *processingBus);
69
+ std::shared_ptr<AudioBus> processInputs(const std::shared_ptr<AudioBus>& outputBus, int framesToProcess);
70
+ std::shared_ptr<AudioBus> applyChannelCountMode(std::shared_ptr<AudioBus> processingBus);
71
+ void mixInputsBuses(const std::shared_ptr<AudioBus>& processingBus);
72
72
 
73
73
  void connectNode(const std::shared_ptr<AudioNode> &node);
74
74
  void disconnectNode(const std::shared_ptr<AudioNode> &node);
@@ -43,7 +43,7 @@ bool AudioScheduledSourceNode::isFinished() {
43
43
  }
44
44
 
45
45
  void AudioScheduledSourceNode::updatePlaybackInfo(
46
- AudioBus *processingBus,
46
+ const std::shared_ptr<AudioBus> &processingBus,
47
47
  int framesToProcess,
48
48
  size_t &startOffset,
49
49
  size_t &nonSilentFramesToProcess) {
@@ -31,7 +31,7 @@ class AudioScheduledSourceNode : public AudioNode {
31
31
  PlaybackState playbackState_;
32
32
 
33
33
  void updatePlaybackInfo(
34
- AudioBus *processingBus,
34
+ const std::shared_ptr<AudioBus>& processingBus,
35
35
  int framesToProcess,
36
36
  size_t &startOffset,
37
37
  size_t &nonSilentFramesToProcess);
@@ -350,7 +350,7 @@ void BiquadFilterNode::applyFilter() {
350
350
  }
351
351
 
352
352
  void BiquadFilterNode::processNode(
353
- AudioBus *processingBus,
353
+ const std::shared_ptr<AudioBus> &processingBus,
354
354
  int framesToProcess) {
355
355
  resetCoefficients();
356
356
  applyFilter();
@@ -32,7 +32,7 @@ class BiquadFilterNode : public AudioNode {
32
32
  std::vector<float> &phaseResponseOutput);
33
33
 
34
34
  protected:
35
- void processNode(AudioBus *processingBus, int framesToProcess) override;
35
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
36
36
 
37
37
  private:
38
38
  std::shared_ptr<AudioParam> frequencyParam_;
@@ -14,7 +14,9 @@ std::shared_ptr<AudioParam> GainNode::getGainParam() const {
14
14
  return gainParam_;
15
15
  }
16
16
 
17
- void GainNode::processNode(AudioBus *processingBus, int framesToProcess) {
17
+ void GainNode::processNode(
18
+ const std::shared_ptr<AudioBus> &processingBus,
19
+ int framesToProcess) {
18
20
  double time = context_->getCurrentTime();
19
21
  double deltaTime = 1.0 / context_->getSampleRate();
20
22
 
@@ -16,7 +16,7 @@ class GainNode : public AudioNode {
16
16
  [[nodiscard]] std::shared_ptr<AudioParam> getGainParam() const;
17
17
 
18
18
  protected:
19
- void processNode(AudioBus *processingBus, int framesToProcess) override;
19
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
20
20
 
21
21
  private:
22
22
  std::shared_ptr<AudioParam> gainParam_;
@@ -38,7 +38,9 @@ void OscillatorNode::setPeriodicWave(
38
38
  type_ = OscillatorType::CUSTOM;
39
39
  }
40
40
 
41
- void OscillatorNode::processNode(AudioBus *processingBus, int framesToProcess) {
41
+ void OscillatorNode::processNode(
42
+ const std::shared_ptr<AudioBus> &processingBus,
43
+ int framesToProcess) {
42
44
  size_t startOffset = 0;
43
45
  size_t offsetLength = 0;
44
46
 
@@ -24,7 +24,7 @@ class OscillatorNode : public AudioScheduledSourceNode {
24
24
  void setPeriodicWave(const std::shared_ptr<PeriodicWave> &periodicWave);
25
25
 
26
26
  protected:
27
- void processNode(AudioBus *processingBus, int framesToProcess) override;
27
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
28
28
 
29
29
  private:
30
30
  std::shared_ptr<AudioParam> frequencyParam_;
@@ -22,7 +22,7 @@ std::shared_ptr<AudioParam> StereoPannerNode::getPanParam() const {
22
22
  }
23
23
 
24
24
  void StereoPannerNode::processNode(
25
- AudioBus *processingBus,
25
+ const std::shared_ptr<AudioBus> &processingBus,
26
26
  int framesToProcess) {
27
27
  double time = context_->getCurrentTime();
28
28
  double deltaTime = 1.0 / context_->getSampleRate();
@@ -17,7 +17,7 @@ class StereoPannerNode : public AudioNode {
17
17
  [[nodiscard]] std::shared_ptr<AudioParam> getPanParam() const;
18
18
 
19
19
  protected:
20
- void processNode(AudioBus *processingBus, int framesToProcess) override;
20
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
21
21
 
22
22
  private:
23
23
  std::shared_ptr<AudioParam> panParam_;
@@ -0,0 +1,49 @@
1
+ // #include "AudioAPIModuleInstaller.h"
2
+ //
3
+ // #include "AudioContext.h"
4
+ // #include "AudioContextHostObject.h"
5
+ //
6
+ // namespace audioapi {
7
+ //
8
+ // AudioAPIModuleInstaller::AudioAPIModuleInstaller(
9
+ // jsi::Runtime *jsiRuntime,
10
+ // const std::shared_ptr<react::CallInvoker> &jsCallInvoker):
11
+ // jsiRuntime_(jsiRuntime), jsCallInvoker_(jsCallInvoker) {}
12
+ //
13
+ // static void AudioAPIModuleInstaller::injectJSIBindings() {
14
+ // auto createAudioContext = getCreateAudioContextFunction();
15
+ // jsiRuntime_->global().setProperty(
16
+ // *jsiRuntime_, "createAudioContext", createAudioContext);
17
+ // }
18
+ //
19
+ // jsi::Function AudioAPIModuleInstaller::getCreateAudioContextFunction() {
20
+ // return jsi::Function::createFromHostFunction(
21
+ // *jsiRuntime_,
22
+ // jsi::PropNameID::forAscii(*jsiRuntime_, "createAudioContext"),
23
+ // 0,
24
+ // [this](
25
+ // jsi::Runtime &runtime,
26
+ // const jsi::Value &thisValue,
27
+ // const jsi::Value *args,
28
+ // size_t count) -> jsi::Value {
29
+ // std::shared_ptr<AudioContext> audioContext;
30
+ // if (args[0].isUndefined()) {
31
+ // audioContext = std::make_shared<AudioContext>();
32
+ // } else {
33
+ // auto sampleRate = static_cast<float>(args[0].getNumber());
34
+ // audioContext = std::make_shared<AudioContext>(sampleRate);
35
+ // }
36
+ //
37
+ // auto promiseVendor = std::make_shared<PromiseVendor>(jsiRuntime_,
38
+ // jsCallInvoker_);
39
+ //
40
+ // auto audioContextHostObject =
41
+ // std::make_shared<AudioContextHostObject>(
42
+ // audioContext, promiseVendor);
43
+ //
44
+ // return jsi::Object::createFromHostObject(
45
+ // runtime, audioContextHostObject);
46
+ // });
47
+ // }
48
+ //
49
+ // } // namespace audioapi
@@ -0,0 +1,49 @@
1
+ #pragma once
2
+
3
+ #include <JsiPromise.h>
4
+ #include "AudioContext.h"
5
+ #include "AudioContextHostObject.h"
6
+
7
+ namespace audioapi {
8
+
9
+ using namespace facebook;
10
+
11
+ class AudioAPIModuleInstaller {
12
+ public:
13
+ static void injectJSIBindings(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
14
+ auto createAudioContext = getCreateAudioContextFunction(jsiRuntime, jsCallInvoker);
15
+ jsiRuntime->global().setProperty(
16
+ *jsiRuntime, "createAudioContext", createAudioContext);
17
+ }
18
+
19
+ private:
20
+ static jsi::Function getCreateAudioContextFunction(jsi::Runtime *jsiRuntime, const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
21
+ return jsi::Function::createFromHostFunction(
22
+ *jsiRuntime,
23
+ jsi::PropNameID::forAscii(*jsiRuntime, "createAudioContext"),
24
+ 0,
25
+ [jsiRuntime, jsCallInvoker](
26
+ jsi::Runtime &runtime,
27
+ const jsi::Value &thisValue,
28
+ const jsi::Value *args,
29
+ size_t count) -> jsi::Value {
30
+ std::shared_ptr<AudioContext> audioContext;
31
+ if (args[0].isUndefined()) {
32
+ audioContext = std::make_shared<AudioContext>();
33
+ } else {
34
+ auto sampleRate = static_cast<float>(args[0].getNumber());
35
+ audioContext = std::make_shared<AudioContext>(sampleRate);
36
+ }
37
+
38
+ auto promiseVendor = std::make_shared<PromiseVendor>(jsiRuntime, jsCallInvoker);
39
+
40
+ auto audioContextHostObject = std::make_shared<AudioContextHostObject>(
41
+ audioContext, promiseVendor);
42
+
43
+ return jsi::Object::createFromHostObject(
44
+ runtime, audioContextHostObject);
45
+ });
46
+ }
47
+ };
48
+
49
+ } // namespace audioapi
@@ -9,7 +9,7 @@
9
9
 
10
10
  @interface AudioAPIModule : RCTEventEmitter
11
11
  #ifdef RCT_NEW_ARCH_ENABLED
12
- <RCTCallInvokerModule>
12
+ <NativeAudioAPIModuleSpec, RCTCallInvokerModule>
13
13
  #else
14
14
  <RCTBridgeModule>
15
15
  #endif // RCT_NEW_ARCH_ENABLED
@@ -6,7 +6,7 @@
6
6
  #import <ReactCommon/RCTTurboModule.h>
7
7
  #endif // RCT_NEW_ARCH_ENABLED
8
8
 
9
- #import "AudioAPIInstallerHostObject.h"
9
+ #include "AudioAPIModuleInstaller.h"
10
10
 
11
11
  @implementation AudioAPIModule
12
12
 
@@ -38,11 +38,18 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
38
38
 
39
39
  assert(jsiRuntime != nullptr);
40
40
 
41
- auto hostObject = std::make_shared<audioapi::AudioAPIInstallerHostObject>(jsiRuntime, jsCallInvoker);
42
- hostObject->install();
41
+ audioapi::AudioAPIModuleInstaller::injectJSIBindings(jsiRuntime, jsCallInvoker);
43
42
 
44
43
  NSLog(@"Successfully installed JSI bindings for react-native-audio-api!");
45
44
  return @true;
46
45
  }
47
46
 
47
+ #ifdef RCT_NEW_ARCH_ENABLED
48
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
49
+ (const facebook::react::ObjCTurboModule::InitParams &)params
50
+ {
51
+ return std::make_shared<facebook::react::NativeAudioAPIModuleSpecJSI>(params);
52
+ }
53
+ #endif // RCT_NEW_ARCH_ENABLED
54
+
48
55
  @end
@@ -7,7 +7,7 @@
7
7
 
8
8
  namespace audioapi {
9
9
 
10
- AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const
10
+ std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(const std::string &path) const
11
11
  {
12
12
  ma_decoder decoder;
13
13
  ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 2, sampleRate_);
@@ -23,7 +23,7 @@ AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const
23
23
  ma_uint64 totalFrameCount;
24
24
  ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrameCount);
25
25
 
26
- auto *audioBus = new AudioBus(static_cast<int>(totalFrameCount), 2, sampleRate_);
26
+ auto audioBus = std::make_shared<AudioBus>(static_cast<int>(totalFrameCount), 2, sampleRate_);
27
27
  auto *buffer = new float[totalFrameCount * 2];
28
28
 
29
29
  ma_uint64 framesDecoded;
@@ -32,7 +32,6 @@ AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const
32
32
  NSLog(@"Failed to decode audio file: %s", path.c_str());
33
33
 
34
34
  delete[] buffer;
35
- delete audioBus;
36
35
  ma_decoder_uninit(&decoder);
37
36
 
38
37
  return nullptr;
@@ -9,10 +9,12 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
9
9
 
10
10
  @property (nonatomic, strong) AVAudioEngine *audioEngine;
11
11
  @property (nonatomic, weak) AVAudioSession *audioSession;
12
+ @property (nonatomic, weak) NSNotificationCenter *notificationCenter;
12
13
  @property (nonatomic, strong) AVAudioFormat *format;
13
14
  @property (nonatomic, strong) AVAudioSourceNode *sourceNode;
14
15
  @property (nonatomic, copy) RenderAudioBlock renderAudio;
15
16
  @property (nonatomic, assign) float sampleRate;
17
+ @property (nonatomic, assign) bool isRunning;
16
18
 
17
19
  - (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio;
18
20
 
@@ -24,6 +26,18 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
24
26
 
25
27
  - (void)stop;
26
28
 
29
+ - (void)resume;
30
+
31
+ - (void)suspend;
32
+
27
33
  - (void)cleanup;
28
34
 
35
+ - (void)setupAndInitAudioSession;
36
+
37
+ - (void)setupAndInitNotificationHandlers;
38
+
39
+ - (void)connectAudioEngine;
40
+
41
+ - (void)handleEngineConfigurationChange:(NSNotification *)notification;
42
+
29
43
  @end
@@ -8,15 +8,11 @@
8
8
  self.renderAudio = [renderAudio copy];
9
9
  self.audioEngine = [[AVAudioEngine alloc] init];
10
10
  self.audioEngine.mainMixerNode.outputVolume = 1;
11
+ self.isRunning = true;
11
12
 
12
- self.audioSession = AVAudioSession.sharedInstance;
13
+ [self setupAndInitAudioSession];
14
+ [self setupAndInitNotificationHandlers];
13
15
 
14
- // TODO:
15
- // We will probably want to change it to AVAudioSessionCategoryPlayAndRecord in the future.
16
- // Eventually we to make this a dynamic setting, if user of the lib wants to use recording features.
17
- // But setting a recording category might require some setup first, so lets skip it for now :)
18
- // [self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
19
- // [self.audioSession setActive:true error:&error];
20
16
 
21
17
  self.sampleRate = [self.audioSession sampleRate];
22
18
 
@@ -45,15 +41,10 @@
45
41
  self.renderAudio = [renderAudio copy];
46
42
  self.audioEngine = [[AVAudioEngine alloc] init];
47
43
  self.audioEngine.mainMixerNode.outputVolume = 1;
44
+ self.isRunning = true;
48
45
 
49
- self.audioSession = AVAudioSession.sharedInstance;
50
-
51
- // TODO:
52
- // We will probably want to change it to AVAudioSessionCategoryPlayAndRecord in the future.
53
- // Eventually we to make this a dynamic setting, if user of the lib wants to use recording features.
54
- // But setting a recording category might require some setup first, so lets skip it for now :)
55
- // [self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
56
- // [self.audioSession setActive:true error:&error];
46
+ [self setupAndInitAudioSession];
47
+ [self setupAndInitNotificationHandlers];
57
48
 
58
49
  self.sampleRate = sampleRate;
59
50
 
@@ -83,19 +74,13 @@
83
74
 
84
75
  - (void)start
85
76
  {
86
- [self.audioEngine attachNode:self.sourceNode];
87
- [self.audioEngine connect:self.sourceNode to:self.audioEngine.mainMixerNode format:self.format];
88
-
89
- if (!self.audioEngine.isRunning) {
90
- NSError *error = nil;
91
- if (![self.audioEngine startAndReturnError:&error]) {
92
- NSLog(@"Error starting audio engine: %@", [error localizedDescription]);
93
- }
94
- }
77
+ self.isRunning = true;
78
+ [self connectAudioEngine];
95
79
  }
96
80
 
97
81
  - (void)stop
98
82
  {
83
+ self.isRunning = false;
99
84
  [self.audioEngine detachNode:self.sourceNode];
100
85
 
101
86
  if (self.audioEngine.isRunning) {
@@ -110,6 +95,19 @@
110
95
  }
111
96
  }
112
97
 
98
+ - (void)suspend
99
+ {
100
+ [self.audioEngine pause];
101
+ self.isRunning = false;
102
+ }
103
+
104
+ - (void)resume
105
+ {
106
+ self.isRunning = true;
107
+ [self setupAndInitAudioSession];
108
+ [self connectAudioEngine];
109
+ }
110
+
113
111
  - (void)cleanup
114
112
  {
115
113
  self.audioEngine = nil;
@@ -131,4 +129,67 @@
131
129
  return noErr;
132
130
  }
133
131
 
132
+ - (void)setupAndInitAudioSession
133
+ {
134
+ NSError *error = nil;
135
+
136
+ if (!self.audioSession) {
137
+ self.audioSession = [AVAudioSession sharedInstance];
138
+ }
139
+
140
+ [self.audioSession setCategory:AVAudioSessionCategoryPlayback
141
+ mode:AVAudioSessionModeDefault
142
+ options:AVAudioSessionCategoryOptionDuckOthers|AVAudioSessionCategoryOptionAllowBluetooth|AVAudioSessionCategoryOptionAllowAirPlay
143
+ error:&error];
144
+
145
+ if (error != nil) {
146
+ NSLog(@"Error while configuring audio session: %@", [error localizedDescription]);
147
+ }
148
+
149
+ [self.audioSession setActive:true error:&error];
150
+
151
+ if (error != nil) {
152
+ NSLog(@"Error while activating audio session: %@", [error localizedDescription]);
153
+ }
154
+ }
155
+
156
+ - (void)setupAndInitNotificationHandlers
157
+ {
158
+ if (!self.notificationCenter) {
159
+ self.notificationCenter = [NSNotificationCenter defaultCenter];
160
+ }
161
+
162
+ [self.notificationCenter addObserver:self
163
+ selector:@selector(handleEngineConfigurationChange:)
164
+ name:AVAudioEngineConfigurationChangeNotification
165
+ object:nil];
166
+ }
167
+
168
+ - (void)connectAudioEngine
169
+ {
170
+ if ([self.audioEngine isRunning]) {
171
+ return;
172
+ }
173
+
174
+ [self.audioEngine attachNode:self.sourceNode];
175
+ [self.audioEngine connect:self.sourceNode to:self.audioEngine.mainMixerNode format:self.format];
176
+
177
+ if (![self.audioEngine isRunning]) {
178
+ NSError *error = nil;
179
+
180
+ if (![self.audioEngine startAndReturnError:&error]) {
181
+ NSLog(@"Error starting audio engine: %@", [error localizedDescription]);
182
+ }
183
+ }
184
+ }
185
+
186
+ - (void)handleEngineConfigurationChange:(NSNotification *)notification
187
+ {
188
+ if (!self.isRunning) {
189
+ return;
190
+ }
191
+
192
+ [self connectAudioEngine];
193
+ }
194
+
134
195
  @end
@@ -15,15 +15,15 @@ class AudioBus;
15
15
 
16
16
  class IOSAudioPlayer {
17
17
  protected:
18
- AudioBus *audioBus_;
18
+ std::shared_ptr<AudioBus> audioBus_;
19
19
  AudioPlayer *audioPlayer_;
20
- std::function<void(AudioBus *, int)> renderAudio_;
20
+ std::function<void(std::shared_ptr<AudioBus>, int)> renderAudio_;
21
21
 
22
22
  public:
23
23
  explicit IOSAudioPlayer(
24
- const std::function<void(AudioBus *, int)> &renderAudio);
24
+ const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio);
25
25
  IOSAudioPlayer(
26
- const std::function<void(AudioBus *, int)> &renderAudio,
26
+ const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio,
27
27
  float sampleRate);
28
28
  ~IOSAudioPlayer();
29
29
 
@@ -31,5 +31,7 @@ class IOSAudioPlayer {
31
31
 
32
32
  void start();
33
33
  void stop();
34
+ void resume();
35
+ void suspend();
34
36
  };
35
37
  } // namespace audioapi
@@ -7,11 +7,9 @@
7
7
 
8
8
  namespace audioapi {
9
9
 
10
- IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio)
10
+ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio)
11
11
  : renderAudio_(renderAudio), audioBus_(0)
12
12
  {
13
- audioBus_ = new AudioBus(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, getSampleRate());
14
-
15
13
  RenderAudioBlock renderAudioBlock = ^(AudioBufferList *outputData, int numFrames) {
16
14
  int processedFrames = 0;
17
15
 
@@ -34,10 +32,10 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &rende
34
32
  };
35
33
 
36
34
  audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudioBlock:renderAudioBlock];
37
- audioBus_ = new AudioBus(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, [audioPlayer_ getSampleRate]);
35
+ audioBus_ = std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, getSampleRate());
38
36
  }
39
37
 
40
- IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio, float sampleRate)
38
+ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio, float sampleRate)
41
39
  : renderAudio_(renderAudio), audioBus_(0)
42
40
  {
43
41
  RenderAudioBlock renderAudioBlock = ^(AudioBufferList *outputData, int numFrames) {
@@ -62,7 +60,7 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &rende
62
60
  };
63
61
 
64
62
  audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudioBlock:renderAudioBlock sampleRate:sampleRate];
65
- audioBus_ = new AudioBus(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, [audioPlayer_ getSampleRate]);
63
+ audioBus_ = std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, getSampleRate());
66
64
  }
67
65
 
68
66
  IOSAudioPlayer::~IOSAudioPlayer()
@@ -71,7 +69,6 @@ IOSAudioPlayer::~IOSAudioPlayer()
71
69
  [audioPlayer_ cleanup];
72
70
 
73
71
  if (audioBus_) {
74
- delete audioBus_;
75
72
  audioBus_ = 0;
76
73
  }
77
74
  }
@@ -86,6 +83,16 @@ void IOSAudioPlayer::stop()
86
83
  return [audioPlayer_ stop];
87
84
  }
88
85
 
86
+ void IOSAudioPlayer::resume()
87
+ {
88
+ return [audioPlayer_ resume];
89
+ }
90
+
91
+ void IOSAudioPlayer::suspend()
92
+ {
93
+ return [audioPlayer_ suspend];
94
+ }
95
+
89
96
  float IOSAudioPlayer::getSampleRate() const
90
97
  {
91
98
  return [audioPlayer_ getSampleRate];
@@ -7,10 +7,16 @@ export default class AudioContext extends BaseAudioContext {
7
7
  if (options && (options.sampleRate < 8000 || options.sampleRate > 96000)) {
8
8
  throw new NotSupportedError(`The provided sampleRate is not supported: ${options.sampleRate}`);
9
9
  }
10
- super(global.__AudioAPIInstaller.createAudioContext(options?.sampleRate));
10
+ super(global.createAudioContext(options?.sampleRate));
11
11
  }
12
12
  async close() {
13
13
  await this.context.close();
14
14
  }
15
+ async resume() {
16
+ await this.context.resume();
17
+ }
18
+ async suspend() {
19
+ await this.context.suspend();
20
+ }
15
21
  }
16
22
  //# sourceMappingURL=AudioContext.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BaseAudioContext","NotSupportedError","AudioContext","constructor","options","sampleRate","global","__AudioAPIInstaller","createAudioContext","close","context"],"sourceRoot":"../../../src","sources":["core/AudioContext.ts"],"mappings":";;AACA,OAAOA,gBAAgB,MAAM,uBAAoB;AAEjD,SAASC,iBAAiB,QAAQ,oBAAW;AAE7C,eAAe,MAAMC,YAAY,SAASF,gBAAgB,CAAC;EACzDG,WAAWA,CAACC,OAA6B,EAAE;IACzC,IAAIA,OAAO,KAAKA,OAAO,CAACC,UAAU,GAAG,IAAI,IAAID,OAAO,CAACC,UAAU,GAAG,KAAK,CAAC,EAAE;MACxE,MAAM,IAAIJ,iBAAiB,CACzB,6CAA6CG,OAAO,CAACC,UAAU,EACjE,CAAC;IACH;IAEA,KAAK,CAACC,MAAM,CAACC,mBAAmB,CAACC,kBAAkB,CAACJ,OAAO,EAAEC,UAAU,CAAC,CAAC;EAC3E;EAEA,MAAMI,KAAKA,CAAA,EAAuB;IAChC,MAAO,IAAI,CAACC,OAAO,CAAmBD,KAAK,CAAC,CAAC;EAC/C;AACF","ignoreList":[]}
1
+ {"version":3,"names":["BaseAudioContext","NotSupportedError","AudioContext","constructor","options","sampleRate","global","createAudioContext","close","context","resume","suspend"],"sourceRoot":"../../../src","sources":["core/AudioContext.ts"],"mappings":";;AACA,OAAOA,gBAAgB,MAAM,uBAAoB;AAEjD,SAASC,iBAAiB,QAAQ,oBAAW;AAE7C,eAAe,MAAMC,YAAY,SAASF,gBAAgB,CAAC;EACzDG,WAAWA,CAACC,OAA6B,EAAE;IACzC,IAAIA,OAAO,KAAKA,OAAO,CAACC,UAAU,GAAG,IAAI,IAAID,OAAO,CAACC,UAAU,GAAG,KAAK,CAAC,EAAE;MACxE,MAAM,IAAIJ,iBAAiB,CACzB,6CAA6CG,OAAO,CAACC,UAAU,EACjE,CAAC;IACH;IAEA,KAAK,CAACC,MAAM,CAACC,kBAAkB,CAACH,OAAO,EAAEC,UAAU,CAAC,CAAC;EACvD;EAEA,MAAMG,KAAKA,CAAA,EAAuB;IAChC,MAAO,IAAI,CAACC,OAAO,CAAmBD,KAAK,CAAC,CAAC;EAC/C;EAEA,MAAME,MAAMA,CAAA,EAAuB;IACjC,MAAO,IAAI,CAACD,OAAO,CAAmBC,MAAM,CAAC,CAAC;EAChD;EAEA,MAAMC,OAAOA,CAAA,EAAuB;IAClC,MAAO,IAAI,CAACF,OAAO,CAAmBE,OAAO,CAAC,CAAC;EACjD;AACF","ignoreList":[]}