react-native-audio-api 0.8.1-nightly-2c9c6a6-20250903 → 0.8.1-nightly-fc8149e-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.
- package/README.md +1 -1
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +4 -0
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +10 -1
- package/android/src/main/cpp/audioapi/android/core/NativeAudioPlayer.hpp +36 -0
- package/android/src/main/java/com/swmansion/audioapi/core/NativeAudioPlayer.kt +24 -0
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +4 -4
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +78 -70
- package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +2 -1
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +3 -11
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +57 -39
- package/android/src/main/res/drawable/logo.xml +16 -0
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +17 -23
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +4 -2
- package/common/cpp/audioapi/core/AudioParam.cpp +205 -254
- package/common/cpp/audioapi/core/AudioParam.h +98 -21
- package/common/cpp/audioapi/core/AudioParamEventQueue.cpp +65 -0
- package/common/cpp/audioapi/core/AudioParamEventQueue.h +63 -0
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +6 -5
- package/common/cpp/audioapi/core/sources/StreamerNode.h +5 -4
- package/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp +2 -39
- package/common/cpp/audioapi/core/utils/ParamChangeEvent.h +53 -12
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +10 -0
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +10 -0
- package/common/cpp/audioapi/utils/CrossThreadEventScheduler.hpp +58 -0
- package/common/cpp/audioapi/utils/RingBiDirectionalBuffer.hpp +199 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +1 -0
- package/lib/commonjs/plugin/withAudioAPI.js +1 -1
- package/lib/commonjs/plugin/withAudioAPI.js.map +1 -1
- package/lib/module/plugin/withAudioAPI.js +1 -1
- package/lib/module/plugin/withAudioAPI.js.map +1 -1
- package/package.json +1 -1
- package/src/plugin/withAudioAPI.ts +1 -1
|
@@ -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
|
|
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
|
-
:
|
|
14
|
+
: context_(context),
|
|
15
|
+
value_(defaultValue),
|
|
17
16
|
defaultValue_(defaultValue),
|
|
18
17
|
minValue_(minValue),
|
|
19
18
|
maxValue_(maxValue),
|
|
20
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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 ¶m) {
|
|
58
|
+
// Ignore events scheduled before the end of existing automation
|
|
59
|
+
if (startTime <= param.getQueueEndTime()) {
|
|
60
|
+
return;
|
|
88
61
|
}
|
|
89
62
|
|
|
90
|
-
|
|
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
|
-
|
|
106
|
-
|
|
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 ¶m) {
|
|
89
|
+
// Ignore events scheduled before the end of existing automation
|
|
90
|
+
if (endTime <= param.getQueueEndTime()) {
|
|
91
|
+
return;
|
|
122
92
|
}
|
|
123
93
|
|
|
124
|
-
|
|
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
|
-
|
|
140
|
-
|
|
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 ¶m) {
|
|
127
|
+
if (endTime <= param.getQueueEndTime()) {
|
|
128
|
+
return;
|
|
157
129
|
}
|
|
158
130
|
|
|
159
|
-
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
166
|
+
auto event = [target, startTime, timeConstant](AudioParam ¶m) {
|
|
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
|
-
|
|
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
|
-
|
|
196
|
+
std::shared_ptr<std::vector<float>> values,
|
|
206
197
|
size_t length,
|
|
207
198
|
double startTime,
|
|
208
199
|
double duration) {
|
|
209
|
-
|
|
210
|
-
|
|
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 ¶m) {
|
|
201
|
+
if (startTime <= param.getQueueEndTime()) {
|
|
202
|
+
return;
|
|
221
203
|
}
|
|
222
204
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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 ¶m) {
|
|
247
|
+
param.eventsQueue_.cancelScheduledValues(cancelTime);
|
|
248
|
+
});
|
|
260
249
|
}
|
|
261
250
|
|
|
262
251
|
void AudioParam::cancelAndHoldAtTime(double cancelTime) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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 ¶m) {
|
|
253
|
+
param.eventsQueue_.cancelAndHoldAtTime(cancelTime, param.endTime_);
|
|
254
|
+
});
|
|
283
255
|
}
|
|
284
256
|
|
|
285
257
|
void AudioParam::addInputNode(AudioNode *node) {
|
|
286
|
-
|
|
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
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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 (
|
|
305
|
-
|
|
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
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
|
|
329
|
-
|
|
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_.
|
|
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
|
|