11#import " NSCAudioContext.h"
2+ #include < stdlib.h>
23
34typedef NS_ENUM (NSInteger , ParamEventType) {
45 ParamEventTypeSet = 0 ,
@@ -23,6 +24,12 @@ - (instancetype)initWithType:(ParamEventType)type time:(double)time value:(doubl
2324}
2425@end
2526
27+ typedef struct {
28+ ParamEventType type;
29+ double time;
30+ double value;
31+ } NSCParamEventSnapshot;
32+
2633@implementation NSCAudioParam {
2734 __strong NSCAudioContext *_context;
2835 NSMutableArray <ParamEvent *> *_events;
@@ -182,7 +189,18 @@ - (BOOL)fillValuesForRange:(double)startTime
182189 return NO ;
183190 }
184191
185- struct { ParamEventType type; double time; double value; } evts[evtCount];
192+ const NSUInteger kStackSnapshotCapacity = 64 ;
193+ NSCParamEventSnapshot stackEvents[kStackSnapshotCapacity ];
194+ NSCParamEventSnapshot *evts = stackEvents;
195+ if (evtCount > kStackSnapshotCapacity ) {
196+ evts = (NSCParamEventSnapshot *)malloc (sizeof (NSCParamEventSnapshot) * evtCount);
197+ if (!evts) {
198+ double cur = _currentValueInternal;
199+ [_lock unlock ];
200+ for (NSInteger i = 0 ; i < frameCount; ++i) outValues[i] = cur;
201+ return NO ;
202+ }
203+ }
186204 for (NSUInteger i = 0 ; i < evtCount; ++i) {
187205 ParamEvent *e = _events[i];
188206 evts[i].type = e.type ;
@@ -214,6 +232,7 @@ - (BOOL)fillValuesForRange:(double)startTime
214232 }
215233 }
216234 for (NSInteger i = 0 ; i < frameCount; ++i) outValues[i] = v;
235+ if (evts != stackEvents) free (evts);
217236 return YES ;
218237 }
219238
@@ -244,77 +263,20 @@ - (BOOL)fillValuesForRange:(double)startTime
244263 }
245264 outValues[i] = value;
246265 }
266+ if (evts != stackEvents) free (evts);
247267 return YES ;
248268}
249269
250270- (NSArray <NSNumber *> *)getValuesForRange : (double )startTime : (double )sampleRate : (NSInteger )frameCount {
251- [_lock lock ];
252- NSArray <ParamEvent *> *evts = [_events copy ];
253- double def = _defaultValue;
254- [_lock unlock ];
255-
271+ if (frameCount <= 0 ) return @[];
272+
273+ NSMutableData *scratch = [NSMutableData dataWithLength: sizeof (double ) * (NSUInteger )frameCount];
274+ double *values = (double *)scratch.mutableBytes ;
275+ [self fillValuesForRange: startTime sampleRate: sampleRate frameCount: frameCount into: values];
276+
256277 NSMutableArray <NSNumber *> *out = [NSMutableArray arrayWithCapacity: frameCount];
257- if ([_automationRate isEqualToString: @" k-rate" ]) {
258- double v = def;
259- if (evts.count == 0 ) {
260- v = def;
261- } else {
262- NSUInteger idx = [evts indexOfObjectPassingTest: ^BOOL (ParamEvent *obj, NSUInteger idx, BOOL *stop) {
263- return obj.time > startTime;
264- }];
265- if (idx == NSNotFound ) {
266- v = evts.lastObject .value ;
267- } else if (idx == 0 ) {
268- v = def;
269- } else {
270- ParamEvent *prev = evts[idx - 1 ];
271- ParamEvent *next = evts[idx];
272- if (next.type == ParamEventTypeLinearRamp) {
273- double t0 = prev.time ;
274- double t1 = next.time ;
275- if (t1 <= t0) v = next.value ;
276- else {
277- double ratio = fmax (0.0 , fmin (1.0 , (startTime - t0) / (t1 - t0)));
278- v = prev.value + (next.value - prev.value ) * ratio;
279- }
280- } else {
281- v = prev.value ;
282- }
283- }
284- }
285- for (NSInteger i = 0 ; i < frameCount; ++i) [out addObject: @(v)];
286- return out;
287- }
288-
289- NSInteger nextEventIndex = 0 ;
290- NSInteger previousEventIndex = -1 ;
291278 for (NSInteger i = 0 ; i < frameCount; ++i) {
292- double t = startTime + (double )i / sampleRate;
293- while (nextEventIndex < evts.count && evts[nextEventIndex].time <= t) {
294- previousEventIndex = nextEventIndex;
295- nextEventIndex += 1 ;
296- }
297- double value;
298- if (previousEventIndex < 0 ) {
299- value = def;
300- } else if (nextEventIndex >= evts.count ) {
301- value = evts[previousEventIndex].value ;
302- } else {
303- ParamEvent *prev = evts[previousEventIndex];
304- ParamEvent *next = evts[nextEventIndex];
305- if (next.type == ParamEventTypeLinearRamp) {
306- double t0 = prev.time ;
307- double t1 = next.time ;
308- if (t1 <= t0) value = next.value ;
309- else {
310- double ratio = fmax (0.0 , fmin (1.0 , (t - t0) / (t1 - t0)));
311- value = prev.value + (next.value - prev.value ) * ratio;
312- }
313- } else {
314- value = prev.value ;
315- }
316- }
317- [out addObject: @(value)];
279+ [out addObject: @(values[i])];
318280 }
319281 return out;
320282}
0 commit comments