react-native-audio-api 0.8.0 → 0.8.1-nightly-da0ddc8-20250904

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 (32) hide show
  1. package/README.md +7 -8
  2. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +4 -0
  3. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +10 -1
  4. package/android/src/main/cpp/audioapi/android/core/NativeAudioPlayer.hpp +36 -0
  5. package/android/src/main/java/com/swmansion/audioapi/core/NativeAudioPlayer.kt +24 -0
  6. package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +4 -4
  7. package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +78 -70
  8. package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +2 -1
  9. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +3 -11
  10. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +57 -39
  11. package/android/src/main/res/drawable/logo.xml +16 -0
  12. package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +17 -23
  13. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +4 -2
  14. package/common/cpp/audioapi/core/AudioParam.cpp +205 -254
  15. package/common/cpp/audioapi/core/AudioParam.h +98 -21
  16. package/common/cpp/audioapi/core/AudioParamEventQueue.cpp +65 -0
  17. package/common/cpp/audioapi/core/AudioParamEventQueue.h +63 -0
  18. package/common/cpp/audioapi/core/sources/StreamerNode.cpp +6 -5
  19. package/common/cpp/audioapi/core/sources/StreamerNode.h +5 -4
  20. package/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp +2 -39
  21. package/common/cpp/audioapi/core/utils/ParamChangeEvent.h +53 -12
  22. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +10 -0
  23. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +10 -0
  24. package/common/cpp/audioapi/utils/CrossThreadEventScheduler.hpp +58 -0
  25. package/common/cpp/audioapi/utils/RingBiDirectionalBuffer.hpp +199 -0
  26. package/ios/audioapi/ios/system/AudioEngine.mm +1 -0
  27. package/lib/commonjs/plugin/withAudioAPI.js +1 -1
  28. package/lib/commonjs/plugin/withAudioAPI.js.map +1 -1
  29. package/lib/module/plugin/withAudioAPI.js +1 -1
  30. package/lib/module/plugin/withAudioAPI.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/plugin/withAudioAPI.ts +1 -1
@@ -25,45 +25,39 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
25
25
  }
26
26
 
27
27
  JSI_HOST_FUNCTION(close) {
28
- auto promise = promiseVendor_->createPromise([this](std::shared_ptr<Promise> promise) {
29
- std::thread([this, promise = std::move(promise)]() {
30
- auto audioContext = std::static_pointer_cast<AudioContext>(context_);
31
- audioContext->close();
28
+ auto audioContext = std::static_pointer_cast<AudioContext>(context_);
29
+ auto promise = promiseVendor_->createPromise([audioContext](const std::shared_ptr<Promise>& promise) {
30
+ audioContext->close();
32
31
 
33
- promise->resolve([](jsi::Runtime &runtime) {
34
- return jsi::Value::undefined();
35
- });
36
- }).detach();
32
+ promise->resolve([](jsi::Runtime &runtime) {
33
+ return jsi::Value::undefined();
34
+ });
37
35
  });
38
36
 
39
37
  return promise;
40
38
  }
41
39
 
42
40
  JSI_HOST_FUNCTION(resume) {
43
- auto promise = promiseVendor_->createPromise([this](std::shared_ptr<Promise> promise) {
44
- std::thread([this, promise = std::move(promise)]() {
45
- auto audioContext = std::static_pointer_cast<AudioContext>(context_);
46
- auto result = audioContext->resume();
41
+ auto audioContext = std::static_pointer_cast<AudioContext>(context_);
42
+ auto promise = promiseVendor_->createPromise([audioContext](const std::shared_ptr<Promise>& promise) {
43
+ auto result = audioContext->resume();
47
44
 
48
- promise->resolve([result](jsi::Runtime &runtime) {
45
+ promise->resolve([result](jsi::Runtime &runtime) {
49
46
  return jsi::Value(result);
50
- });
51
- }).detach();
47
+ });
52
48
  });
53
49
 
54
50
  return promise;
55
51
  }
56
52
 
57
53
  JSI_HOST_FUNCTION(suspend) {
58
- auto promise = promiseVendor_->createPromise([this](std::shared_ptr<Promise> promise) {
59
- std::thread([this, promise = std::move(promise)]() {
60
- auto audioContext = std::static_pointer_cast<AudioContext>(context_);
61
- auto result = audioContext->suspend();
54
+ auto audioContext = std::static_pointer_cast<AudioContext>(context_);
55
+ auto promise = promiseVendor_->createPromise([audioContext](const std::shared_ptr<Promise>& promise) {
56
+ auto result = audioContext->suspend();
62
57
 
63
- promise->resolve([result](jsi::Runtime &runtime) {
64
- return jsi::Value(result);
65
- });
66
- }).detach();
58
+ promise->resolve([result](jsi::Runtime &runtime) {
59
+ return jsi::Value(result);
60
+ });
67
61
  });
68
62
 
69
63
  return promise;
@@ -4,6 +4,7 @@
4
4
  #include <audioapi/core/AudioParam.h>
5
5
 
6
6
  #include <jsi/jsi.h>
7
+ #include <utility>
7
8
  #include <memory>
8
9
  #include <vector>
9
10
  #include <cstddef>
@@ -81,12 +82,13 @@ class AudioParamHostObject : public JsiHostObject {
81
82
 
82
83
  JSI_HOST_FUNCTION(setValueCurveAtTime) {
83
84
  auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
84
- auto values = reinterpret_cast<float *>(arrayBuffer.data(runtime));
85
+ auto rawValues = reinterpret_cast<float *>(arrayBuffer.data(runtime));
85
86
  auto length = static_cast<int>(arrayBuffer.size(runtime));
87
+ auto values = std::make_unique<std::vector<float>>(rawValues, rawValues + length);
86
88
 
87
89
  double startTime = args[1].getNumber();
88
90
  double duration = args[2].getNumber();
89
- param_->setValueCurveAtTime(values, length, startTime, duration);
91
+ param_->setValueCurveAtTime(std::move(values), length, startTime, duration);
90
92
  return jsi::Value::undefined();
91
93
  }
92
94
 
@@ -1,10 +1,8 @@
1
1
  #include <audioapi/core/AudioParam.h>
2
2
  #include <audioapi/core/BaseAudioContext.h>
3
- #include <audioapi/core/utils/Locker.h>
4
3
  #include <audioapi/dsp/AudioUtils.h>
5
4
  #include <audioapi/dsp/VectorMath.h>
6
5
  #include <audioapi/utils/AudioArray.h>
7
- #include <iostream>
8
6
 
9
7
  namespace audioapi {
10
8
 
@@ -13,287 +11,260 @@ AudioParam::AudioParam(
13
11
  float minValue,
14
12
  float maxValue,
15
13
  BaseAudioContext *context)
16
- : value_(defaultValue),
14
+ : context_(context),
15
+ value_(defaultValue),
17
16
  defaultValue_(defaultValue),
18
17
  minValue_(minValue),
19
18
  maxValue_(maxValue),
20
- context_(context),
19
+ eventsQueue_(),
20
+ eventScheduler_(32),
21
21
  audioBus_(
22
22
  std::make_shared<AudioBus>(
23
23
  RENDER_QUANTUM_SIZE,
24
24
  1,
25
25
  context->getSampleRate())) {
26
+ inputBuses_.reserve(4);
27
+ inputNodes_.reserve(4);
26
28
  startTime_ = 0;
27
29
  endTime_ = 0;
28
30
  startValue_ = value_;
29
31
  endValue_ = value_;
32
+ // Default calculation function just returns the static value
30
33
  calculateValue_ = [this](double, double, float, float, double) {
31
34
  return value_;
32
35
  };
33
36
  }
34
37
 
35
- float AudioParam::getValue() const {
36
- return value_;
37
- }
38
-
39
- float AudioParam::getDefaultValue() const {
40
- return defaultValue_;
41
- }
42
-
43
- float AudioParam::getMinValue() const {
44
- return minValue_;
45
- }
46
-
47
- float AudioParam::getMaxValue() const {
48
- return maxValue_;
49
- }
50
-
51
- std::mutex &AudioParam::getQueueLock() {
52
- return queueLock_;
53
- }
54
-
55
- void AudioParam::setValue(float value) {
56
- value_ = std::clamp(value, minValue_, maxValue_);
57
- }
58
-
59
38
  float AudioParam::getValueAtTime(double time) {
60
- Locker lock(getQueueLock());
61
- if (endTime_ < time && !eventsQueue_.empty()) {
62
- auto event = eventsQueue_.front();
39
+ // Check if current automation segment has ended and we need to advance to
40
+ // next event
41
+ if (endTime_ < time && !eventsQueue_.isEmpty()) {
42
+ ParamChangeEvent event;
43
+ eventsQueue_.popFront(event);
63
44
  startTime_ = event.getStartTime();
64
45
  endTime_ = event.getEndTime();
65
46
  startValue_ = event.getStartValue();
66
47
  endValue_ = event.getEndValue();
67
- calculateValue_ = event.getCalculateValue();
68
- eventsQueue_.pop_front();
48
+ calculateValue_ = std::move(event.getCalculateValue());
69
49
  }
70
50
 
51
+ // Calculate value using the current automation function and clamp to valid
71
52
  setValue(calculateValue_(startTime_, endTime_, startValue_, endValue_, time));
72
-
73
53
  return value_;
74
54
  }
75
55
 
76
56
  void AudioParam::setValueAtTime(float value, double startTime) {
77
- if (startTime <= getQueueEndTime()) {
78
- return;
79
- }
80
-
81
- auto calculateValue = [](double startTime,
82
- double,
83
- float startValue,
84
- float endValue,
85
- double time) {
86
- if (time < startTime) {
87
- return startValue;
57
+ auto event = [value, startTime](AudioParam &param) {
58
+ // Ignore events scheduled before the end of existing automation
59
+ if (startTime <= param.getQueueEndTime()) {
60
+ return;
88
61
  }
89
62
 
90
- return endValue;
63
+ // Step function: instant change at startTime
64
+ auto calculateValue = [](double startTime,
65
+ double /* endTime */,
66
+ float startValue,
67
+ float endValue,
68
+ double time) {
69
+ if (time < startTime) {
70
+ return startValue;
71
+ }
72
+
73
+ return endValue;
74
+ };
75
+
76
+ param.updateQueue(ParamChangeEvent(
77
+ startTime,
78
+ startTime,
79
+ param.getQueueEndValue(),
80
+ value,
81
+ std::move(calculateValue),
82
+ ParamChangeEventType::SET_VALUE));
91
83
  };
92
-
93
- Locker lock(getQueueLock());
94
- auto event = ParamChangeEvent(
95
- startTime,
96
- startTime,
97
- getQueueEndValue(),
98
- value,
99
- calculateValue,
100
- ParamChangeEventType::SET_VALUE);
101
- updateQueue(event);
84
+ eventScheduler_.scheduleEvent(std::move(event));
102
85
  }
103
86
 
104
87
  void AudioParam::linearRampToValueAtTime(float value, double endTime) {
105
- if (endTime <= getQueueEndTime()) {
106
- return;
107
- }
108
-
109
- auto calculateValue = [](double startTime,
110
- double endTime,
111
- float startValue,
112
- float endValue,
113
- double time) {
114
- if (time < startTime) {
115
- return startValue;
116
- }
117
-
118
- if (time < endTime) {
119
- return static_cast<float>(
120
- startValue +
121
- (endValue - startValue) * (time - startTime) / (endTime - startTime));
88
+ auto event = [value, endTime](AudioParam &param) {
89
+ // Ignore events scheduled before the end of existing automation
90
+ if (endTime <= param.getQueueEndTime()) {
91
+ return;
122
92
  }
123
93
 
124
- return endValue;
94
+ // Linear interpolation function
95
+ auto calculateValue = [](double startTime,
96
+ double endTime,
97
+ float startValue,
98
+ float endValue,
99
+ double time) {
100
+ if (time < startTime) {
101
+ return startValue;
102
+ }
103
+
104
+ if (time < endTime) {
105
+ return static_cast<float>(
106
+ startValue +
107
+ (endValue - startValue) * (time - startTime) /
108
+ (endTime - startTime));
109
+ }
110
+
111
+ return endValue;
112
+ };
113
+
114
+ param.updateQueue(ParamChangeEvent(
115
+ param.getQueueEndTime(),
116
+ endTime,
117
+ param.getQueueEndValue(),
118
+ value,
119
+ std::move(calculateValue),
120
+ ParamChangeEventType::LINEAR_RAMP));
125
121
  };
126
-
127
- Locker lock(getQueueLock());
128
- auto event = ParamChangeEvent(
129
- getQueueEndTime(),
130
- endTime,
131
- getQueueEndValue(),
132
- value,
133
- calculateValue,
134
- ParamChangeEventType::LINEAR_RAMP);
135
- updateQueue(event);
122
+ eventScheduler_.scheduleEvent(std::move(event));
136
123
  }
137
124
 
138
125
  void AudioParam::exponentialRampToValueAtTime(float value, double endTime) {
139
- if (endTime <= getQueueEndTime()) {
140
- return;
141
- }
142
-
143
- auto calculateValue = [](double startTime,
144
- double endTime,
145
- float startValue,
146
- float endValue,
147
- double time) {
148
- if (time < startTime) {
149
- return startValue;
150
- }
151
-
152
- if (time < endTime) {
153
- return static_cast<float>(
154
- startValue *
155
- pow(endValue / startValue,
156
- (time - startTime) / (endTime - startTime)));
126
+ auto event = [value, endTime](AudioParam &param) {
127
+ if (endTime <= param.getQueueEndTime()) {
128
+ return;
157
129
  }
158
130
 
159
- return endValue;
131
+ // Exponential curve function using power law
132
+ auto calculateValue = [](double startTime,
133
+ double endTime,
134
+ float startValue,
135
+ float endValue,
136
+ double time) {
137
+ if (time < startTime) {
138
+ return startValue;
139
+ }
140
+
141
+ if (time < endTime) {
142
+ return static_cast<float>(
143
+ startValue *
144
+ pow(endValue / startValue,
145
+ (time - startTime) / (endTime - startTime)));
146
+ }
147
+
148
+ return endValue;
149
+ };
150
+
151
+ param.updateQueue(ParamChangeEvent(
152
+ param.getQueueEndTime(),
153
+ endTime,
154
+ param.getQueueEndValue(),
155
+ value,
156
+ std::move(calculateValue),
157
+ ParamChangeEventType::EXPONENTIAL_RAMP));
160
158
  };
161
-
162
- Locker lock(getQueueLock());
163
- auto event = ParamChangeEvent(
164
- getQueueEndTime(),
165
- endTime,
166
- getQueueEndValue(),
167
- value,
168
- calculateValue,
169
- ParamChangeEventType::EXPONENTIAL_RAMP);
170
- updateQueue(event);
159
+ eventScheduler_.scheduleEvent(std::move(event));
171
160
  }
172
161
 
173
162
  void AudioParam::setTargetAtTime(
174
163
  float target,
175
164
  double startTime,
176
165
  double timeConstant) {
177
- if (startTime <= getQueueEndTime()) {
178
- return;
179
- }
180
-
181
- auto calculateValue =
182
- [timeConstant, target](
183
- double startTime, double, float startValue, float, double time) {
184
- if (time < startTime) {
185
- return startValue;
186
- }
166
+ auto event = [target, startTime, timeConstant](AudioParam &param) {
167
+ if (startTime <= param.getQueueEndTime()) {
168
+ return;
169
+ }
170
+ // Exponential decay function towards target value
171
+ auto calculateValue =
172
+ [timeConstant, target](
173
+ double startTime, double, float startValue, float, double time) {
174
+ if (time < startTime) {
175
+ return startValue;
176
+ }
177
+
178
+ return static_cast<float>(
179
+ target +
180
+ (startValue - target) * exp(-(time - startTime) / timeConstant));
181
+ };
182
+ param.updateQueue(ParamChangeEvent(
183
+ startTime,
184
+ startTime, // SetTarget events have infinite duration conceptually
185
+ param.getQueueEndValue(),
186
+ param.getQueueEndValue(), // End value is not meaningful for
187
+ // infinite events
188
+ std::move(calculateValue),
189
+ ParamChangeEventType::SET_TARGET));
190
+ };
187
191
 
188
- return static_cast<float>(
189
- target +
190
- (startValue - target) * exp(-(time - startTime) / timeConstant));
191
- };
192
-
193
- Locker lock(getQueueLock());
194
- auto event = ParamChangeEvent(
195
- startTime,
196
- startTime,
197
- getQueueEndValue(),
198
- getQueueEndValue(),
199
- calculateValue,
200
- ParamChangeEventType::SET_TARGET);
201
- updateQueue(event);
192
+ eventScheduler_.scheduleEvent(std::move(event));
202
193
  }
203
194
 
204
195
  void AudioParam::setValueCurveAtTime(
205
- const float *values,
196
+ std::shared_ptr<std::vector<float>> values,
206
197
  size_t length,
207
198
  double startTime,
208
199
  double duration) {
209
- if (startTime <= getQueueEndTime()) {
210
- return;
211
- }
212
-
213
- auto calculateValue = [&values, length](
214
- double startTime,
215
- double endTime,
216
- float startValue,
217
- float endValue,
218
- double time) {
219
- if (time < startTime) {
220
- return startValue;
200
+ auto event = [values, length, startTime, duration](AudioParam &param) {
201
+ if (startTime <= param.getQueueEndTime()) {
202
+ return;
221
203
  }
222
204
 
223
- if (time < endTime) {
224
- auto k = static_cast<int>(std::floor(
225
- static_cast<double>(length - 1) / (endTime - startTime) *
226
- (time - startTime)));
227
- auto factor = static_cast<float>(
228
- k -
229
- (time - startTime) * static_cast<double>(length - 1) /
230
- (endTime - startTime));
231
-
232
- return dsp::linearInterpolate(values, k, k + 1, factor);
233
- }
234
-
235
- return endValue;
205
+ auto calculateValue = [values, length](
206
+ double startTime,
207
+ double endTime,
208
+ float startValue,
209
+ float endValue,
210
+ double time) {
211
+ if (time < startTime) {
212
+ return startValue;
213
+ }
214
+
215
+ if (time < endTime) {
216
+ // Calculate position in the array based on time progress
217
+ auto k = static_cast<int>(std::floor(
218
+ static_cast<double>(length - 1) / (endTime - startTime) *
219
+ (time - startTime)));
220
+ // Calculate interpolation factor between adjacent array elements
221
+ auto factor = static_cast<float>(
222
+ k -
223
+ (time - startTime) * static_cast<double>(length - 1) /
224
+ (endTime - startTime));
225
+ return dsp::linearInterpolate(values->data(), k, k + 1, factor);
226
+ }
227
+
228
+ return endValue;
229
+ };
230
+
231
+ param.updateQueue(ParamChangeEvent(
232
+ startTime,
233
+ startTime + duration,
234
+ param.getQueueEndValue(),
235
+ values->at(length - 1),
236
+ std::move(calculateValue),
237
+ ParamChangeEventType::SET_VALUE_CURVE));
236
238
  };
237
239
 
238
- Locker lock(getQueueLock());
239
- auto event = ParamChangeEvent(
240
- startTime,
241
- startTime + duration,
242
- getQueueEndValue(),
243
- values[length - 1],
244
- calculateValue,
245
- ParamChangeEventType::SET_VALUE_CURVE);
246
- updateQueue(event);
240
+ /// Schedules an event that modifies this param
241
+ /// It will be executed on next audio render cycle
242
+ eventScheduler_.scheduleEvent(std::move(event));
247
243
  }
248
244
 
249
245
  void AudioParam::cancelScheduledValues(double cancelTime) {
250
- Locker lock(getQueueLock());
251
- auto it = eventsQueue_.rbegin();
252
- while (it->getEndTime() >= cancelTime) {
253
- if (it->getStartTime() >= cancelTime ||
254
- it->getType() == ParamChangeEventType::SET_VALUE_CURVE) {
255
- eventsQueue_.pop_back();
256
- }
257
-
258
- it++;
259
- }
246
+ eventScheduler_.scheduleEvent([cancelTime](AudioParam &param) {
247
+ param.eventsQueue_.cancelScheduledValues(cancelTime);
248
+ });
260
249
  }
261
250
 
262
251
  void AudioParam::cancelAndHoldAtTime(double cancelTime) {
263
- Locker lock(getQueueLock());
264
- auto it = eventsQueue_.rbegin();
265
- while (it->getEndTime() >= cancelTime) {
266
- if (it->getStartTime() >= cancelTime) {
267
- eventsQueue_.pop_back();
268
- }
269
-
270
- it++;
271
- }
272
-
273
- if (eventsQueue_.empty()) {
274
- endTime_ = cancelTime;
275
- }
276
-
277
- if (!eventsQueue_.empty()) {
278
- auto lastEvent = eventsQueue_.rbegin();
279
- if (lastEvent->getEndTime() > cancelTime) {
280
- lastEvent->setEndTime(cancelTime);
281
- }
282
- }
252
+ eventScheduler_.scheduleEvent([cancelTime](AudioParam &param) {
253
+ param.eventsQueue_.cancelAndHoldAtTime(cancelTime, param.endTime_);
254
+ });
283
255
  }
284
256
 
285
257
  void AudioParam::addInputNode(AudioNode *node) {
286
- auto position = inputNodes_.find(node);
287
- if (position == inputNodes_.end()) {
288
- inputNodes_.insert(node);
289
- }
258
+ inputNodes_.emplace_back(node);
290
259
  }
291
260
 
292
261
  void AudioParam::removeInputNode(AudioNode *node) {
293
- auto position = inputNodes_.find(node);
294
-
295
- if (position != inputNodes_.end()) {
296
- inputNodes_.erase(position);
262
+ for (int i = 0; i < inputNodes_.size(); i++) {
263
+ if (inputNodes_[i] == node) {
264
+ std::swap(inputNodes_[i], inputNodes_.back());
265
+ inputNodes_.resize(inputNodes_.size() - 1);
266
+ break;
267
+ }
297
268
  }
298
269
  }
299
270
 
@@ -301,64 +272,41 @@ std::shared_ptr<AudioBus> AudioParam::calculateInputs(
301
272
  const std::shared_ptr<AudioBus> &processingBus,
302
273
  int framesToProcess) {
303
274
  processingBus->zero();
304
- if (!inputNodes_.empty()) {
305
- processInputs(processingBus, framesToProcess, true);
306
- mixInputsBuses(processingBus);
275
+ if (inputNodes_.empty()) {
276
+ return processingBus;
307
277
  }
278
+ processInputs(processingBus, framesToProcess, true);
279
+ mixInputsBuses(processingBus);
308
280
  return processingBus;
309
281
  }
310
282
 
311
283
  std::shared_ptr<AudioBus> AudioParam::processARateParam(
312
284
  int framesToProcess,
313
285
  double time) {
286
+ processScheduledEvents();
314
287
  auto processingBus = calculateInputs(audioBus_, framesToProcess);
315
- for (size_t i = 0; i < framesToProcess; i++) {
316
- auto sample = getValueAtTime(time + i / context_->getSampleRate());
317
- processingBus->getChannel(0)->getData()[i] += sample;
288
+
289
+ float sampleRate = context_->getSampleRate();
290
+ float *busData = processingBus->getChannel(0)->getData();
291
+ float timeCache = time;
292
+ float timeStep = 1.0f / sampleRate;
293
+ float sample = 0.0f;
294
+
295
+ // Add automated parameter value to each sample
296
+ for (size_t i = 0; i < framesToProcess; i++, timeCache += timeStep) {
297
+ sample = getValueAtTime(timeCache);
298
+ busData[i] += sample;
318
299
  }
319
- // processingBus is a mono bus
300
+ // processingBus is a mono bus containing per-sample parameter values
320
301
  return processingBus;
321
302
  }
322
303
 
323
304
  float AudioParam::processKRateParam(int framesToProcess, double time) {
305
+ processScheduledEvents();
324
306
  auto processingBus = calculateInputs(audioBus_, framesToProcess);
325
- return processingBus->getChannel(0)->getData()[0] + getValueAtTime(time);
326
- }
327
307
 
328
- double AudioParam::getQueueEndTime() {
329
- if (eventsQueue_.empty()) {
330
- return endTime_;
331
- }
332
-
333
- return eventsQueue_.back().getEndTime();
334
- }
335
-
336
- float AudioParam::getQueueEndValue() {
337
- if (eventsQueue_.empty()) {
338
- return this->endValue_;
339
- }
340
-
341
- return eventsQueue_.back().getEndValue();
342
- }
343
-
344
- void AudioParam::updateQueue(ParamChangeEvent &event) {
345
- if (!eventsQueue_.empty()) {
346
- auto prev = eventsQueue_.back();
347
-
348
- if (prev.getType() == ParamChangeEventType::SET_TARGET) {
349
- prev.setEndTime(event.getStartTime());
350
- prev.setEndValue(prev.getCalculateValue()(
351
- prev.getStartTime(),
352
- prev.getEndTime(),
353
- prev.getStartValue(),
354
- prev.getEndValue(),
355
- event.getStartTime()));
356
- }
357
-
358
- event.setStartValue(prev.getEndValue());
359
- }
360
-
361
- eventsQueue_.push_back(event);
308
+ // Return block-rate parameter value plus first sample of input modulation
309
+ return processingBus->getChannel(0)->getData()[0] + getValueAtTime(time);
362
310
  }
363
311
 
364
312
  void AudioParam::processInputs(
@@ -374,9 +322,10 @@ void AudioParam::processInputs(
374
322
  continue;
375
323
  }
376
324
 
325
+ // Process this input node and store its output bus
377
326
  auto inputBus = inputNode->processAudio(
378
327
  outputBus, framesToProcess, checkIsAlreadyProcessed);
379
- inputBuses_.push_back(inputBus);
328
+ inputBuses_.emplace_back(inputBus);
380
329
  }
381
330
  }
382
331
 
@@ -384,11 +333,13 @@ void AudioParam::mixInputsBuses(
384
333
  const std::shared_ptr<AudioBus> &processingBus) {
385
334
  assert(processingBus != nullptr);
386
335
 
336
+ // Sum all input buses into the processing bus
387
337
  for (auto it = inputBuses_.begin(), end = inputBuses_.end(); it != end;
388
338
  ++it) {
389
339
  processingBus->sum(it->get(), ChannelInterpretation::SPEAKERS);
390
340
  }
391
341
 
342
+ // Clear for next processing cycle
392
343
  inputBuses_.clear();
393
344
  }
394
345