-
Notifications
You must be signed in to change notification settings - Fork 872
/
Copy pathDSPKernel.mm
83 lines (64 loc) · 2.42 KB
/
DSPKernel.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
See LICENSE.txt for this sample’s licensing information.
Abstract:
Utility code to manage scheduled parameters in an audio unit implementation.
*/
#import "DSPKernel.hpp"
void DSPKernel::handleOneEvent(AURenderEvent const *event) {
switch (event->head.eventType) {
case AURenderEventParameter:
case AURenderEventParameterRamp: {
AUParameterEvent const& paramEvent = event->parameter;
startRamp(paramEvent.parameterAddress, paramEvent.value, paramEvent.rampDurationSampleFrames);
break;
}
case AURenderEventMIDI:
handleMIDIEvent(event->MIDI);
break;
default:
break;
}
}
void DSPKernel::performAllSimultaneousEvents(AUEventSampleTime now, AURenderEvent const *&event, AUMIDIOutputEventBlock midiOut) {
do {
handleOneEvent(event);
if (event->head.eventType == AURenderEventMIDI && midiOut)
{
midiOut(now, 0, event->MIDI.length, event->MIDI.data);
}
// Go to next event.
event = event->head.next;
// While event is not null and is simultaneous (or late).
} while (event && event->head.eventSampleTime <= now);
}
/**
This function handles the event list processing and rendering loop for you.
Call it inside your internalRenderBlock.
*/
void DSPKernel::processWithEvents(AudioTimeStamp const *timestamp, AUAudioFrameCount frameCount, AURenderEvent const *events, AUMIDIOutputEventBlock midiOut) {
AUEventSampleTime now = AUEventSampleTime(timestamp->mSampleTime);
AUAudioFrameCount framesRemaining = frameCount;
AURenderEvent const *event = events;
while (framesRemaining > 0) {
// If there are no more events, we can process the entire remaining segment and exit.
if (event == nullptr) {
AUAudioFrameCount const bufferOffset = frameCount - framesRemaining;
process(framesRemaining, bufferOffset);
return;
}
// **** start late events late.
auto timeZero = AUEventSampleTime(0);
auto headEventTime = event->head.eventSampleTime;
AUAudioFrameCount const framesThisSegment = AUAudioFrameCount(std::max(timeZero, headEventTime - now));
// Compute everything before the next event.
if (framesThisSegment > 0) {
AUAudioFrameCount const bufferOffset = frameCount - framesRemaining;
process(framesThisSegment, bufferOffset);
// Advance frames.
framesRemaining -= framesThisSegment;
// Advance time.
now += AUEventSampleTime(framesThisSegment);
}
performAllSimultaneousEvents(now, event, midiOut);
}
}