react-native-audio-api 0.3.0-rc2 → 0.3.2

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 (197) hide show
  1. package/RNAudioAPI.podspec +40 -29
  2. package/android/CMakeLists.txt +17 -21
  3. package/android/build.gradle +26 -9
  4. package/android/src/main/cpp/OnLoad.cpp +1 -1
  5. package/android/src/main/cpp/core/AudioAPIInstaller.cpp +37 -0
  6. package/android/src/main/cpp/{AudioAPIInstaller → core}/AudioAPIInstaller.h +5 -16
  7. package/android/src/main/cpp/{AudioDecoder → core}/AudioDecoder.cpp +0 -8
  8. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +2 -0
  9. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +6 -4
  10. package/common/cpp/HostObjects/AudioAPIInstallerHostObject.h +48 -0
  11. package/common/cpp/HostObjects/AudioBufferHostObject.h +79 -13
  12. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +93 -14
  13. package/common/cpp/HostObjects/AudioContextHostObject.h +10 -21
  14. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +3 -16
  15. package/common/cpp/HostObjects/AudioNodeHostObject.h +48 -11
  16. package/common/cpp/HostObjects/AudioParamHostObject.h +93 -14
  17. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.h +23 -16
  18. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +131 -14
  19. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.h +76 -18
  20. package/common/cpp/HostObjects/GainNodeHostObject.h +10 -15
  21. package/common/cpp/HostObjects/OscillatorNodeHostObject.h +40 -17
  22. package/common/cpp/HostObjects/PeriodicWaveHostObject.h +4 -17
  23. package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +10 -17
  24. package/common/cpp/core/AudioBufferSourceNode.cpp +181 -73
  25. package/common/cpp/core/AudioBufferSourceNode.h +41 -1
  26. package/{android/src/main/cpp/AudioDecoder → common/cpp/core}/AudioDecoder.h +1 -3
  27. package/common/cpp/core/AudioDestinationNode.h +1 -1
  28. package/common/cpp/core/AudioParam.cpp +218 -58
  29. package/common/cpp/core/AudioParam.h +19 -15
  30. package/common/cpp/core/AudioScheduledSourceNode.cpp +94 -21
  31. package/common/cpp/core/AudioScheduledSourceNode.h +16 -5
  32. package/common/cpp/core/BaseAudioContext.cpp +3 -13
  33. package/common/cpp/core/BaseAudioContext.h +2 -4
  34. package/common/cpp/core/BiquadFilterNode.cpp +5 -7
  35. package/common/cpp/{HostObjects → core}/Constants.h +2 -2
  36. package/common/cpp/core/GainNode.cpp +1 -1
  37. package/common/cpp/core/OscillatorNode.cpp +11 -5
  38. package/common/cpp/core/ParamChangeEvent.cpp +58 -0
  39. package/common/cpp/core/{ParamChange.h → ParamChangeEvent.h} +11 -5
  40. package/common/cpp/core/StereoPannerNode.cpp +1 -1
  41. package/common/cpp/jsi/JsiHostObject.cpp +90 -0
  42. package/common/cpp/jsi/JsiHostObject.h +100 -0
  43. package/common/cpp/{utils → jsi}/JsiPromise.cpp +10 -9
  44. package/common/cpp/jsi/JsiPromise.h +48 -0
  45. package/common/cpp/jsi/RuntimeAwareCache.h +57 -0
  46. package/common/cpp/jsi/RuntimeLifecycleMonitor.cpp +61 -0
  47. package/common/cpp/jsi/RuntimeLifecycleMonitor.h +32 -0
  48. package/common/cpp/types/BiquadFilterType.h +0 -4
  49. package/common/cpp/types/ChannelCountMode.h +0 -3
  50. package/common/cpp/types/ChannelInterpretation.h +0 -3
  51. package/common/cpp/types/ContextState.h +0 -3
  52. package/common/cpp/types/OscillatorType.h +0 -4
  53. package/common/cpp/types/ParamChangeEventType.h +13 -0
  54. package/common/cpp/utils/AudioUtils.cpp +26 -0
  55. package/common/cpp/utils/AudioUtils.h +12 -0
  56. package/common/cpp/utils/{ios/FFTFrame.cpp → FFTFrame.cpp} +30 -3
  57. package/common/cpp/utils/VectorMath.h +7 -33
  58. package/ios/AudioAPIModule.h +4 -12
  59. package/ios/AudioAPIModule.mm +26 -25
  60. package/ios/core/AudioDecoder.mm +45 -0
  61. package/ios/{AudioPlayer → core}/AudioPlayer.m +2 -1
  62. package/lib/module/core/AudioBuffer.js +3 -1
  63. package/lib/module/core/AudioBuffer.js.map +1 -1
  64. package/lib/module/core/AudioBufferSourceNode.js +19 -2
  65. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  66. package/lib/module/core/AudioContext.js +3 -1
  67. package/lib/module/core/AudioContext.js.map +1 -1
  68. package/lib/module/core/AudioDestinationNode.js +4 -6
  69. package/lib/module/core/AudioDestinationNode.js.map +1 -1
  70. package/lib/module/core/AudioNode.js +3 -1
  71. package/lib/module/core/AudioNode.js.map +1 -1
  72. package/lib/module/core/AudioParam.js +27 -1
  73. package/lib/module/core/AudioParam.js.map +1 -1
  74. package/lib/module/core/AudioScheduledSourceNode.js +4 -5
  75. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
  76. package/lib/module/core/BaseAudioContext.js +11 -9
  77. package/lib/module/core/BaseAudioContext.js.map +1 -1
  78. package/lib/module/core/BiquadFilterNode.js +5 -3
  79. package/lib/module/core/BiquadFilterNode.js.map +1 -1
  80. package/lib/module/core/GainNode.js +4 -2
  81. package/lib/module/core/GainNode.js.map +1 -1
  82. package/lib/module/core/OscillatorNode.js +5 -3
  83. package/lib/module/core/OscillatorNode.js.map +1 -1
  84. package/lib/module/core/PeriodicWave.js +2 -0
  85. package/lib/module/core/PeriodicWave.js.map +1 -1
  86. package/lib/module/core/StereoPannerNode.js +4 -2
  87. package/lib/module/core/StereoPannerNode.js.map +1 -1
  88. package/lib/module/core/types.js +1 -1
  89. package/lib/module/errors/IndexSizeError.js +2 -0
  90. package/lib/module/errors/IndexSizeError.js.map +1 -1
  91. package/lib/module/errors/InvalidAccessError.js +2 -0
  92. package/lib/module/errors/InvalidAccessError.js.map +1 -1
  93. package/lib/module/errors/InvalidStateError.js +2 -0
  94. package/lib/module/errors/InvalidStateError.js.map +1 -1
  95. package/lib/module/errors/RangeError.js +2 -0
  96. package/lib/module/errors/RangeError.js.map +1 -1
  97. package/lib/module/errors/index.js +6 -4
  98. package/lib/module/errors/index.js.map +1 -1
  99. package/lib/module/index.js +35 -10
  100. package/lib/module/index.js.map +1 -1
  101. package/lib/module/index.native.js +16 -14
  102. package/lib/module/index.native.js.map +1 -1
  103. package/lib/module/interfaces.js +2 -0
  104. package/lib/module/specs/global.d.js +4 -0
  105. package/lib/module/{modules → specs}/global.d.js.map +1 -1
  106. package/lib/module/{utils → specs}/install.js +5 -9
  107. package/lib/module/specs/install.js.map +1 -0
  108. package/lib/typescript/core/AudioBuffer.d.ts +2 -0
  109. package/lib/typescript/core/AudioBuffer.d.ts.map +1 -1
  110. package/lib/typescript/core/AudioBufferSourceNode.d.ts +7 -0
  111. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
  112. package/lib/typescript/core/AudioDestinationNode.d.ts +0 -3
  113. package/lib/typescript/core/AudioDestinationNode.d.ts.map +1 -1
  114. package/lib/typescript/core/AudioParam.d.ts +4 -0
  115. package/lib/typescript/core/AudioParam.d.ts.map +1 -1
  116. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +0 -3
  117. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
  118. package/lib/typescript/core/PeriodicWave.d.ts +2 -0
  119. package/lib/typescript/core/PeriodicWave.d.ts.map +1 -1
  120. package/lib/typescript/index.d.ts +13 -3
  121. package/lib/typescript/index.d.ts.map +1 -1
  122. package/lib/typescript/interfaces.d.ts +8 -0
  123. package/lib/typescript/interfaces.d.ts.map +1 -1
  124. package/lib/typescript/{utils → specs}/install.d.ts.map +1 -1
  125. package/metro-config/index.d.ts +5 -0
  126. package/metro-config/index.js +41 -0
  127. package/metro-config/tsconfig.json +3 -0
  128. package/package.json +50 -16
  129. package/scripts/audioapi_utils.rb +56 -0
  130. package/src/core/AudioBufferSourceNode.ts +23 -0
  131. package/src/core/AudioDestinationNode.ts +1 -7
  132. package/src/core/AudioParam.ts +48 -0
  133. package/src/core/AudioScheduledSourceNode.ts +0 -5
  134. package/src/index.native.ts +1 -1
  135. package/src/index.ts +54 -13
  136. package/src/interfaces.ts +17 -0
  137. package/src/{modules → specs}/global.d.ts +2 -0
  138. package/src/{utils → specs}/install.ts +4 -11
  139. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +0 -26
  140. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +0 -58
  141. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +0 -51
  142. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerWrapper.h +0 -38
  143. package/common/cpp/AudioAPIInstaller/android/AudioAPIInstallerWrapper.cpp +0 -16
  144. package/common/cpp/AudioAPIInstaller/ios/AudioAPIInstallerWrapper.cpp +0 -12
  145. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +0 -150
  146. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +0 -79
  147. package/common/cpp/HostObjects/AudioContextHostObject.cpp +0 -55
  148. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +0 -33
  149. package/common/cpp/HostObjects/AudioNodeHostObject.cpp +0 -102
  150. package/common/cpp/HostObjects/AudioParamHostObject.cpp +0 -115
  151. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.cpp +0 -73
  152. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +0 -250
  153. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +0 -125
  154. package/common/cpp/HostObjects/GainNodeHostObject.cpp +0 -41
  155. package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +0 -88
  156. package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +0 -33
  157. package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +0 -41
  158. package/common/cpp/core/ParamChange.cpp +0 -46
  159. package/common/cpp/utils/JsiPromise.h +0 -48
  160. package/common/cpp/utils/android/FFTFrame.cpp +0 -23
  161. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +0 -45
  162. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +0 -26
  163. package/common/cpp/wrappers/AudioBufferWrapper.cpp +0 -46
  164. package/common/cpp/wrappers/AudioBufferWrapper.h +0 -30
  165. package/common/cpp/wrappers/AudioContextWrapper.cpp +0 -17
  166. package/common/cpp/wrappers/AudioContextWrapper.h +0 -19
  167. package/common/cpp/wrappers/AudioDestinationNodeWrapper.h +0 -16
  168. package/common/cpp/wrappers/AudioNodeWrapper.cpp +0 -37
  169. package/common/cpp/wrappers/AudioNodeWrapper.h +0 -25
  170. package/common/cpp/wrappers/AudioParamWrapper.cpp +0 -42
  171. package/common/cpp/wrappers/AudioParamWrapper.h +0 -25
  172. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.cpp +0 -23
  173. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.h +0 -23
  174. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +0 -83
  175. package/common/cpp/wrappers/BaseAudioContextWrapper.h +0 -51
  176. package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +0 -60
  177. package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +0 -37
  178. package/common/cpp/wrappers/GainNodeWrapper.cpp +0 -14
  179. package/common/cpp/wrappers/GainNodeWrapper.h +0 -20
  180. package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +0 -44
  181. package/common/cpp/wrappers/OscillatorNodeWrapper.h +0 -31
  182. package/common/cpp/wrappers/PeriodicWaveWrapper.h +0 -17
  183. package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +0 -16
  184. package/common/cpp/wrappers/StereoPannerNodeWrapper.h +0 -21
  185. package/ios/AudioDecoder/AudioDecoder.h +0 -17
  186. package/ios/AudioDecoder/AudioDecoder.m +0 -80
  187. package/ios/AudioDecoder/IOSAudioDecoder.h +0 -28
  188. package/ios/AudioDecoder/IOSAudioDecoder.mm +0 -46
  189. package/lib/module/modules/global.d.js +0 -2
  190. package/lib/module/utils/install.js.map +0 -1
  191. /package/android/src/main/cpp/{AudioPlayer → core}/AudioPlayer.cpp +0 -0
  192. /package/android/src/main/cpp/{AudioPlayer → core}/AudioPlayer.h +0 -0
  193. /package/{android/libs/include → common/cpp/libs}/miniaudio.h +0 -0
  194. /package/ios/{AudioPlayer → core}/AudioPlayer.h +0 -0
  195. /package/ios/{AudioPlayer → core}/IOSAudioPlayer.h +0 -0
  196. /package/ios/{AudioPlayer → core}/IOSAudioPlayer.mm +0 -0
  197. /package/lib/typescript/{utils → specs}/install.d.ts +0 -0
@@ -1,23 +1,19 @@
1
1
  #include "AudioParam.h"
2
+
3
+ #include "AudioUtils.h"
2
4
  #include "BaseAudioContext.h"
3
5
 
4
6
  namespace audioapi {
5
7
 
6
- AudioParam::AudioParam(
7
- BaseAudioContext *context,
8
- float defaultValue,
9
- float minValue,
10
- float maxValue)
8
+ AudioParam::AudioParam(float defaultValue, float minValue, float maxValue)
11
9
  : value_(defaultValue),
12
10
  defaultValue_(defaultValue),
13
11
  minValue_(minValue),
14
- maxValue_(maxValue),
15
- context_(context),
16
- changesQueue_() {
12
+ maxValue_(maxValue) {
17
13
  startTime_ = 0;
18
14
  endTime_ = 0;
19
- startValue_ = 0;
20
- endValue_ = 0;
15
+ startValue_ = value_;
16
+ endValue_ = value_;
21
17
  calculateValue_ = [this](double, double, float, float, double) {
22
18
  return value_;
23
19
  };
@@ -40,94 +36,258 @@ float AudioParam::getMaxValue() const {
40
36
  }
41
37
 
42
38
  void AudioParam::setValue(float value) {
43
- value_ = checkValue(value);
39
+ value_ = std::clamp(value, minValue_, maxValue_);
44
40
  }
45
41
 
46
42
  float AudioParam::getValueAtTime(double time) {
47
- if (!changesQueue_.empty()) {
48
- if (endTime_ < time) {
49
- auto change = *changesQueue_.begin();
50
- startTime_ = change.getStartTime();
51
- endTime_ = change.getEndTime();
52
- startValue_ = change.getStartValue();
53
- endValue_ = change.getEndValue();
54
- calculateValue_ = change.getCalculateValue();
55
- changesQueue_.erase(changesQueue_.begin());
56
- }
43
+ if (endTime_ < time && !eventsQueue_.empty()) {
44
+ auto event = eventsQueue_.front();
45
+ startTime_ = event.getStartTime();
46
+ endTime_ = event.getEndTime();
47
+ startValue_ = event.getStartValue();
48
+ endValue_ = event.getEndValue();
49
+ calculateValue_ = event.getCalculateValue();
50
+ eventsQueue_.pop_front();
57
51
  }
58
52
 
59
- if (startTime_ <= time) {
60
- value_ =
61
- calculateValue_(startTime_, endTime_, startValue_, endValue_, time);
62
- }
53
+ setValue(calculateValue_(startTime_, endTime_, startValue_, endValue_, time));
63
54
 
64
55
  return value_;
65
56
  }
66
57
 
67
- void AudioParam::setValueAtTime(float value, double time) {
68
- value = checkValue(value);
69
- auto calculateValue = [](double, double, float, float endValue, double) {
58
+ void AudioParam::setValueAtTime(float value, double startTime) {
59
+ if (startTime <= getQueueEndTime()) {
60
+ return;
61
+ }
62
+
63
+ auto calculateValue = [](double startTime,
64
+ double,
65
+ float startValue,
66
+ float endValue,
67
+ double time) {
68
+ if (time < startTime) {
69
+ return startValue;
70
+ }
71
+
70
72
  return endValue;
71
73
  };
72
74
 
73
- auto paramChange = ParamChange(time, time, value, value, calculateValue);
74
- changesQueue_.insert(paramChange);
75
+ auto event = ParamChangeEvent(
76
+ startTime,
77
+ startTime,
78
+ getQueueEndValue(),
79
+ value,
80
+ calculateValue,
81
+ ParamChangeEventType::SET_VALUE);
82
+ updateQueue(event);
75
83
  }
76
84
 
77
- void AudioParam::linearRampToValueAtTime(float value, double time) {
78
- value = checkValue(value);
85
+ void AudioParam::linearRampToValueAtTime(float value, double endTime) {
86
+ if (endTime <= getQueueEndTime()) {
87
+ return;
88
+ }
89
+
79
90
  auto calculateValue = [](double startTime,
80
91
  double endTime,
81
92
  float startValue,
82
93
  float endValue,
83
94
  double time) {
84
- return time >= endTime ? endValue
85
- : startValue +
86
- (endValue - startValue) * (time - startTime) /
87
- (endTime - startTime);
95
+ if (time < startTime) {
96
+ return startValue;
97
+ }
98
+
99
+ if (time < endTime) {
100
+ return static_cast<float>(
101
+ startValue +
102
+ (endValue - startValue) * (time - startTime) / (endTime - startTime));
103
+ }
104
+
105
+ return endValue;
88
106
  };
89
107
 
90
- auto paramChange =
91
- ParamChange(getStartTime(), time, getStartValue(), value, calculateValue);
92
- changesQueue_.emplace(paramChange);
108
+ auto event = ParamChangeEvent(
109
+ getQueueEndTime(),
110
+ endTime,
111
+ getQueueEndValue(),
112
+ value,
113
+ calculateValue,
114
+ ParamChangeEventType::LINEAR_RAMP);
115
+ updateQueue(event);
93
116
  }
94
117
 
95
- void AudioParam::exponentialRampToValueAtTime(float value, double time) {
96
- value = checkValue(value);
118
+ void AudioParam::exponentialRampToValueAtTime(float value, double endTime) {
119
+ if (endTime <= getQueueEndTime()) {
120
+ return;
121
+ }
122
+
97
123
  auto calculateValue = [](double startTime,
98
124
  double endTime,
99
125
  float startValue,
100
126
  float endValue,
101
127
  double time) {
102
- return time >= endTime ? endValue
103
- : startValue *
104
- pow(endValue / startValue,
105
- (time - startTime) / (endTime - startTime));
128
+ if (time < startTime) {
129
+ return startValue;
130
+ }
131
+
132
+ if (time < endTime) {
133
+ return static_cast<float>(
134
+ startValue *
135
+ pow(endValue / startValue,
136
+ (time - startTime) / (endTime - startTime)));
137
+ }
138
+
139
+ return endValue;
106
140
  };
107
141
 
108
- auto paramChange =
109
- ParamChange(getStartTime(), time, getStartValue(), value, calculateValue);
110
- changesQueue_.emplace(paramChange);
142
+ auto event = ParamChangeEvent(
143
+ getQueueEndTime(),
144
+ endTime,
145
+ getQueueEndValue(),
146
+ value,
147
+ calculateValue,
148
+ ParamChangeEventType::EXPONENTIAL_RAMP);
149
+ updateQueue(event);
111
150
  }
112
151
 
113
- float AudioParam::checkValue(float value) const {
114
- return std::clamp(value, minValue_, maxValue_);
152
+ void AudioParam::setTargetAtTime(
153
+ float target,
154
+ double startTime,
155
+ double timeConstant) {
156
+ if (startTime <= getQueueEndTime()) {
157
+ return;
158
+ }
159
+
160
+ auto calculateValue =
161
+ [timeConstant, target](
162
+ double startTime, double, float startValue, float, double time) {
163
+ if (time < startTime) {
164
+ return startValue;
165
+ }
166
+
167
+ return static_cast<float>(
168
+ target +
169
+ (startValue - target) * exp(-(time - startTime) / timeConstant));
170
+ };
171
+
172
+ auto event = ParamChangeEvent(
173
+ startTime,
174
+ startTime,
175
+ getQueueEndValue(),
176
+ getQueueEndValue(),
177
+ calculateValue,
178
+ ParamChangeEventType::SET_TARGET);
179
+ updateQueue(event);
115
180
  }
116
181
 
117
- double AudioParam::getStartTime() {
118
- if (changesQueue_.empty()) {
119
- return context_->getCurrentTime();
182
+ void AudioParam::setValueCurveAtTime(
183
+ const float *values,
184
+ int length,
185
+ double startTime,
186
+ double duration) {
187
+ if (startTime <= getQueueEndTime()) {
188
+ return;
120
189
  }
121
190
 
122
- return changesQueue_.rbegin()->getEndTime();
191
+ auto calculateValue = [&values, length](
192
+ double startTime,
193
+ double endTime,
194
+ float startValue,
195
+ float endValue,
196
+ double time) {
197
+ if (time < startTime) {
198
+ return startValue;
199
+ }
200
+
201
+ if (time < endTime) {
202
+ auto k = static_cast<int>(std::floor(
203
+ (length - 1) / (endTime - startTime) * (time - startTime)));
204
+ auto factor = static_cast<float>(
205
+ k - (time - startTime) * (length - 1) / (endTime - startTime));
206
+
207
+ return AudioUtils::linearInterpolate(values, k, k + 1, factor);
208
+ }
209
+
210
+ return endValue;
211
+ };
212
+
213
+ auto event = ParamChangeEvent(
214
+ startTime,
215
+ startTime + duration,
216
+ getQueueEndValue(),
217
+ values[length - 1],
218
+ calculateValue,
219
+ ParamChangeEventType::SET_VALUE_CURVE);
220
+ updateQueue(event);
221
+ }
222
+
223
+ void AudioParam::cancelScheduledValues(double cancelTime) {
224
+ auto it = eventsQueue_.rbegin();
225
+ while (it->getEndTime() >= cancelTime) {
226
+ if (it->getStartTime() >= cancelTime ||
227
+ it->getType() == ParamChangeEventType::SET_VALUE_CURVE) {
228
+ eventsQueue_.pop_back();
229
+ }
230
+
231
+ it++;
232
+ }
123
233
  }
124
234
 
125
- float AudioParam::getStartValue() {
126
- if (changesQueue_.empty()) {
127
- return this->value_;
235
+ void AudioParam::cancelAndHoldAtTime(double cancelTime) {
236
+ auto it = eventsQueue_.rbegin();
237
+ while (it->getEndTime() >= cancelTime) {
238
+ if (it->getStartTime() >= cancelTime) {
239
+ eventsQueue_.pop_back();
240
+ }
241
+
242
+ it++;
243
+ }
244
+
245
+ if (eventsQueue_.empty()) {
246
+ endTime_ = cancelTime;
247
+ }
248
+
249
+ if (!eventsQueue_.empty()) {
250
+ auto lastEvent = eventsQueue_.rbegin();
251
+ if (lastEvent->getEndTime() > cancelTime) {
252
+ lastEvent->setEndTime(cancelTime);
253
+ }
254
+ }
255
+ }
256
+
257
+ double AudioParam::getQueueEndTime() {
258
+ if (eventsQueue_.empty()) {
259
+ return endTime_;
260
+ }
261
+
262
+ return eventsQueue_.back().getEndTime();
263
+ }
264
+
265
+ float AudioParam::getQueueEndValue() {
266
+ if (eventsQueue_.empty()) {
267
+ return this->endValue_;
268
+ }
269
+
270
+ return eventsQueue_.back().getEndValue();
271
+ }
272
+
273
+ void AudioParam::updateQueue(ParamChangeEvent &event) {
274
+ if (!eventsQueue_.empty()) {
275
+ auto prev = eventsQueue_.back();
276
+
277
+ if (prev.getType() == ParamChangeEventType::SET_TARGET) {
278
+ prev.setEndTime(event.getStartTime());
279
+ prev.setEndValue(prev.getCalculateValue()(
280
+ prev.getStartTime(),
281
+ prev.getEndTime(),
282
+ prev.getStartValue(),
283
+ prev.getEndValue(),
284
+ event.getStartTime()));
285
+ }
286
+
287
+ event.setStartValue(prev.getEndValue());
128
288
  }
129
289
 
130
- return changesQueue_.rbegin()->getEndValue();
290
+ eventsQueue_.push_back(event);
131
291
  }
132
292
 
133
293
  } // namespace audioapi
@@ -1,40 +1,44 @@
1
1
  #pragma once
2
2
 
3
+ #include <deque>
3
4
  #include <memory>
4
- #include <set>
5
5
  #include <vector>
6
6
 
7
- #include "ParamChange.h"
7
+ #include "ParamChangeEvent.h"
8
+ #include "ParamChangeEventType.h"
8
9
 
9
10
  namespace audioapi {
10
11
 
11
- class BaseAudioContext;
12
-
13
12
  class AudioParam {
14
13
  public:
15
- explicit AudioParam(
16
- BaseAudioContext *context,
17
- float defaultValue,
18
- float minValue,
19
- float maxValue);
14
+ explicit AudioParam(float defaultValue, float minValue, float maxValue);
20
15
 
21
16
  [[nodiscard]] float getValue() const;
22
17
  float getValueAtTime(double time);
23
- void setValue(float value);
24
18
  [[nodiscard]] float getDefaultValue() const;
25
19
  [[nodiscard]] float getMinValue() const;
26
20
  [[nodiscard]] float getMaxValue() const;
21
+
22
+ void setValue(float value);
23
+
27
24
  void setValueAtTime(float value, double startTime);
28
25
  void linearRampToValueAtTime(float value, double endTime);
29
26
  void exponentialRampToValueAtTime(float value, double endTime);
27
+ void setTargetAtTime(float target, double startTime, double timeConstant);
28
+ void setValueCurveAtTime(
29
+ const float *values,
30
+ int length,
31
+ double startTime,
32
+ double duration);
33
+ void cancelScheduledValues(double cancelTime);
34
+ void cancelAndHoldAtTime(double cancelTime);
30
35
 
31
36
  private:
32
37
  float value_;
33
38
  float defaultValue_;
34
39
  float minValue_;
35
40
  float maxValue_;
36
- BaseAudioContext *context_;
37
- std::set<ParamChange> changesQueue_;
41
+ std::deque<ParamChangeEvent> eventsQueue_;
38
42
 
39
43
  double startTime_;
40
44
  double endTime_;
@@ -42,9 +46,9 @@ class AudioParam {
42
46
  float endValue_;
43
47
  std::function<float(double, double, float, float, double)> calculateValue_;
44
48
 
45
- float checkValue(float value) const;
46
- double getStartTime();
47
- float getStartValue();
49
+ double getQueueEndTime();
50
+ float getQueueEndValue();
51
+ void updateQueue(ParamChangeEvent &event);
48
52
  };
49
53
 
50
54
  } // namespace audioapi
@@ -1,24 +1,37 @@
1
1
  #include "AudioScheduledSourceNode.h"
2
+ #include "AudioArray.h"
3
+ #include "AudioBus.h"
2
4
  #include "AudioNodeManager.h"
5
+ #include "AudioUtils.h"
3
6
  #include "BaseAudioContext.h"
4
7
 
5
8
  namespace audioapi {
6
9
 
7
10
  AudioScheduledSourceNode::AudioScheduledSourceNode(BaseAudioContext *context)
8
- : AudioNode(context), playbackState_(PlaybackState::UNSCHEDULED) {
11
+ : AudioNode(context),
12
+ playbackState_(PlaybackState::UNSCHEDULED),
13
+ startTime_(-1.0),
14
+ stopTime_(-1.0) {
9
15
  numberOfInputs_ = 0;
10
- isInitialized_ = true;
11
16
  }
12
17
 
13
18
  void AudioScheduledSourceNode::start(double time) {
14
- context_->getNodeManager()->addSourceNode(shared_from_this());
15
-
16
19
  playbackState_ = PlaybackState::SCHEDULED;
17
- waitAndExecute(time, [this](double time) { startPlayback(); });
20
+ startTime_ = time;
21
+
22
+ context_->getNodeManager()->addSourceNode(shared_from_this());
18
23
  }
19
24
 
20
25
  void AudioScheduledSourceNode::stop(double time) {
21
- waitAndExecute(time, [this](double time) { stopPlayback(); });
26
+ stopTime_ = time;
27
+ }
28
+
29
+ bool AudioScheduledSourceNode::isUnscheduled() {
30
+ return playbackState_ == PlaybackState::UNSCHEDULED;
31
+ }
32
+
33
+ bool AudioScheduledSourceNode::isScheduled() {
34
+ return playbackState_ == PlaybackState::SCHEDULED;
22
35
  }
23
36
 
24
37
  bool AudioScheduledSourceNode::isPlaying() {
@@ -29,25 +42,85 @@ bool AudioScheduledSourceNode::isFinished() {
29
42
  return playbackState_ == PlaybackState::FINISHED;
30
43
  }
31
44
 
32
- void AudioScheduledSourceNode::startPlayback() {
33
- playbackState_ = PlaybackState::PLAYING;
34
- }
45
+ void AudioScheduledSourceNode::updatePlaybackInfo(
46
+ AudioBus *processingBus,
47
+ int framesToProcess,
48
+ size_t &startOffset,
49
+ size_t &nonSilentFramesToProcess) {
50
+ if (!isInitialized_) {
51
+ startOffset = 0;
52
+ nonSilentFramesToProcess = 0;
53
+ return;
54
+ }
35
55
 
36
- void AudioScheduledSourceNode::stopPlayback() {
37
- playbackState_ = PlaybackState::FINISHED;
38
- disable();
39
- }
56
+ int sampleRate = context_->getSampleRate();
40
57
 
41
- void AudioScheduledSourceNode::waitAndExecute(
42
- double time,
43
- const std::function<void(double)> &fun) {
44
- std::thread([this, time, fun]() {
45
- while (context_->getCurrentTime() < time) {
46
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
58
+ size_t firstFrame = context_->getCurrentSampleFrame();
59
+ size_t lastFrame = firstFrame + framesToProcess;
60
+
61
+ size_t startFrame = std::max(
62
+ AudioUtils::timeToSampleFrame(startTime_, sampleRate), firstFrame);
63
+ size_t stopFrame = stopTime_ == -1.0
64
+ ? std::numeric_limits<size_t>::max()
65
+ : std::max(
66
+ AudioUtils::timeToSampleFrame(stopTime_, sampleRate), firstFrame);
67
+
68
+ if (isUnscheduled() || isFinished()) {
69
+ startOffset = 0;
70
+ nonSilentFramesToProcess = 0;
71
+ return;
72
+ }
73
+
74
+ if (isScheduled()) {
75
+ // not yet playing
76
+ if (startFrame > lastFrame) {
77
+ startOffset = 0;
78
+ nonSilentFramesToProcess = 0;
79
+ return;
47
80
  }
48
81
 
49
- fun(time);
50
- }).detach();
82
+ // start playing
83
+ // zero first frames before starting frame
84
+ playbackState_ = PlaybackState::PLAYING;
85
+ startOffset = std::max(startFrame, firstFrame) - firstFrame > 0
86
+ ? std::max(startFrame, firstFrame) - firstFrame
87
+ : 0;
88
+ nonSilentFramesToProcess =
89
+ std::min(lastFrame, stopFrame) - startFrame;
90
+ processingBus->zero(0, startOffset);
91
+ return;
92
+ }
93
+
94
+ // the node is playing
95
+
96
+ // stop will happen in this render quantum
97
+ // zero remaining frames after stop frame
98
+ if (stopFrame < lastFrame && stopFrame >= firstFrame) {
99
+ startOffset = 0;
100
+ nonSilentFramesToProcess = stopFrame - firstFrame;
101
+ processingBus->zero(stopFrame - firstFrame, lastFrame - stopFrame);
102
+ return;
103
+ }
104
+
105
+ // mark as finished in first silent render quantum
106
+ if (stopFrame < firstFrame) {
107
+ startOffset = 0;
108
+ nonSilentFramesToProcess = 0;
109
+ playbackState_ = PlaybackState::FINISHED;
110
+ disable();
111
+ return;
112
+ }
113
+
114
+ // normal "mid-buffer" playback
115
+ startOffset = 0;
116
+ nonSilentFramesToProcess = framesToProcess;
117
+ }
118
+
119
+ void AudioScheduledSourceNode::handleStopScheduled() {
120
+ if (isPlaying() && stopTime_ > 0 && context_->getCurrentTime() >= stopTime_) {
121
+ playbackState_ = PlaybackState::FINISHED;
122
+ disable();
123
+ }
51
124
  }
52
125
 
53
126
  } // namespace audioapi
@@ -1,9 +1,11 @@
1
1
  #pragma once
2
2
 
3
+ #include <algorithm>
3
4
  #include <atomic>
4
5
  #include <chrono>
5
6
  #include <functional>
6
7
  #include <iostream>
8
+ #include <limits>
7
9
  #include <memory>
8
10
  #include <thread>
9
11
 
@@ -19,16 +21,25 @@ class AudioScheduledSourceNode : public AudioNode {
19
21
  void start(double time);
20
22
  void stop(double time);
21
23
 
22
- bool isFinished();
24
+ bool isUnscheduled();
25
+ bool isScheduled();
23
26
  bool isPlaying();
27
+ bool isFinished();
24
28
 
25
29
  protected:
26
- std::atomic<PlaybackState> playbackState_;
30
+ PlaybackState playbackState_;
31
+
32
+ void updatePlaybackInfo(
33
+ AudioBus *processingBus,
34
+ int framesToProcess,
35
+ size_t &startOffset,
36
+ size_t &nonSilentFramesToProcess);
37
+
38
+ void handleStopScheduled();
27
39
 
28
40
  private:
29
- void startPlayback();
30
- void stopPlayback();
31
- void waitAndExecute(double time, const std::function<void(double)> &fun);
41
+ double startTime_;
42
+ double stopTime_;
32
43
  };
33
44
 
34
45
  } // namespace audioapi
@@ -1,8 +1,6 @@
1
1
  #ifdef ANDROID
2
- #include "AudioDecoder.h"
3
2
  #include "AudioPlayer.h"
4
3
  #else
5
- #include "IOSAudioDecoder.h"
6
4
  #include "IOSAudioPlayer.h"
7
5
  #endif
8
6
 
@@ -12,6 +10,7 @@
12
10
  #include "AudioBuffer.h"
13
11
  #include "AudioBufferSourceNode.h"
14
12
  #include "AudioBus.h"
13
+ #include "AudioDecoder.h"
15
14
  #include "AudioDestinationNode.h"
16
15
  #include "AudioNodeManager.h"
17
16
  #include "BiquadFilterNode.h"
@@ -25,13 +24,12 @@ namespace audioapi {
25
24
  BaseAudioContext::BaseAudioContext() {
26
25
  #ifdef ANDROID
27
26
  audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
28
- audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());
29
27
  #else
30
28
  audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
31
- audioDecoder_ =
32
- std::make_shared<IOSAudioDecoder>(audioPlayer_->getSampleRate());
33
29
  #endif
34
30
 
31
+ audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());
32
+
35
33
  sampleRate_ = audioPlayer_->getSampleRate();
36
34
  bufferSizeInFrames_ = audioPlayer_->getBufferSizeInFrames();
37
35
 
@@ -108,19 +106,11 @@ std::shared_ptr<PeriodicWave> BaseAudioContext::createPeriodicWave(
108
106
  sampleRate_, real, imag, length, disableNormalization);
109
107
  }
110
108
 
111
- #ifdef ANDROID
112
109
  std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
113
110
  const std::string &path) {
114
111
  auto audioBus = audioDecoder_->decodeWithFilePath(path);
115
112
  return std::make_shared<AudioBuffer>(audioBus);
116
113
  }
117
- #else
118
- std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
119
- const std::string &path) {
120
- auto audioBus = audioDecoder_->decodeWithFilePath(path);
121
- return std::make_shared<AudioBuffer>(audioBus);
122
- }
123
- #endif
124
114
 
125
115
  std::function<void(AudioBus *, int)> BaseAudioContext::renderAudio() {
126
116
  if (!isRunning()) {
@@ -21,13 +21,12 @@ class AudioNodeManager;
21
21
  class BiquadFilterNode;
22
22
  class AudioDestinationNode;
23
23
  class AudioBufferSourceNode;
24
+ class AudioDecoder;
24
25
 
25
26
  #ifdef ANDROID
26
27
  class AudioPlayer;
27
- class AudioDecoder;
28
28
  #else
29
29
  class IOSAudioPlayer;
30
- class IOSAudioDecoder;
31
30
  #endif
32
31
 
33
32
  class BaseAudioContext {
@@ -65,13 +64,12 @@ class BaseAudioContext {
65
64
  protected:
66
65
  static std::string toString(ContextState state);
67
66
  std::shared_ptr<AudioDestinationNode> destination_;
67
+ std::shared_ptr<AudioDecoder> audioDecoder_;
68
68
 
69
69
  #ifdef ANDROID
70
70
  std::shared_ptr<AudioPlayer> audioPlayer_;
71
- std::shared_ptr<AudioDecoder> audioDecoder_;
72
71
  #else
73
72
  std::shared_ptr<IOSAudioPlayer> audioPlayer_;
74
- std::shared_ptr<IOSAudioDecoder> audioDecoder_;
75
73
  #endif
76
74
 
77
75
  int sampleRate_;
@@ -11,13 +11,11 @@ namespace audioapi {
11
11
  BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context)
12
12
  : AudioNode(context) {
13
13
  frequencyParam_ = std::make_shared<AudioParam>(
14
- context, 350.0, MIN_FILTER_FREQUENCY, MAX_FILTER_FREQUENCY);
15
- detuneParam_ =
16
- std::make_shared<AudioParam>(context, 0.0, -MAX_DETUNE, MAX_DETUNE);
17
- QParam_ =
18
- std::make_shared<AudioParam>(context, 1.0, -MAX_FILTER_Q, MAX_FILTER_Q);
19
- gainParam_ = std::make_shared<AudioParam>(
20
- context, 0.0, MIN_FILTER_GAIN, MAX_FILTER_GAIN);
14
+ 350.0, MIN_FILTER_FREQUENCY, MAX_FILTER_FREQUENCY);
15
+ detuneParam_ = std::make_shared<AudioParam>(0.0, -MAX_DETUNE, MAX_DETUNE);
16
+ QParam_ = std::make_shared<AudioParam>(1.0, -MAX_FILTER_Q, MAX_FILTER_Q);
17
+ gainParam_ =
18
+ std::make_shared<AudioParam>(0.0, MIN_FILTER_GAIN, MAX_FILTER_GAIN);
21
19
  type_ = BiquadFilterType::LOWPASS;
22
20
  isInitialized_ = true;
23
21
  }