123 void Tremolo::process ( float **inputs, float
**outputs, long sampleFrames)
124 {
125 float *in1 = inputs[0];
126 float *in2 = inputs[1];
127 float *out1 = outputs[0];
128 float *out2 = outputs[1];
129 float sampleRate = updateSampleRate();
130 float modifier;
131
132 while (--sampleFrames >= 0)
133 {
134 // increment our
counter
135 if (counter < ((1/fFrequency
* 10) * sampleRate))
136 {
137 counter++;
138 }
139 else
140 {
141 counter
= 0;
142 }
143
144 // calculate the multiplier
145 modifier = (1.0 - fDepth) + fDepth * (sin((2
* 3.14 * (fFrequency * 10)) * (counter/sampleRate))) * (sin((2 * 3.14
* (fFrequency * 10)) * (counter/sampleRate)));
146
147 (*out1++) += (*in1++) * modifier; // replacing
148 (*out2++) += (*in2++) * modifier;
149 }
150 } |
Our process function begins like the gain example.
However at line 129 we have a new local variable called “sampleRate” that
grabs a value from the function updateSampleRate() ,
provided by the audioEffectX class. We will need the sample
rate in conjunction with our global counter to calculate our
time beyond the audio buffer provided by the host application.
The audio buffer may be shorter than one cycle of our frequency
setting so having a sample counter outside of the process() function
allows us to maintain our position in the cycle once we have
run out of audio in the buffer and have to restart the process() function.
Line 130 declares a temporary modifier float variable to be
used to store the calculation of our tremolo modifier.
The while loop still operates as it does in
the AGain example by stopping when we run out of audio buffer
samples. Our first step within the loop is to check and or
increment our counter variable. Line 135 checks to see if the
counter value has exceeded one cycle as definied by our user
in the “fFrequency” variable. The equation to the right of
the < symbol calculates how many samples there should be
in one cycle for the given frequency parameter. The fFrequency
value is multiplied by 10 to reach a hertz value. Then we take
the inverse of the resultant value to get the period of the
cycle in seconds. Because the sample rate represents the number
of samples provided in one second of audio we can multiply
the period by the sample rate to find out how many samples
there are in one cycle.
For example if we use the default parameter
value of .1 we convert it to 1 hertz by multiplying it by 10.
Then inverting 1 hertz gives us a period of 1 second and if
we multiply that by a typical sample rate of 44100 samples/second
we get 44100 samples per cycle which seems intuitively correct.
Each time the loop runs through an iteration
we have processed one sample of audio and the counter will
hold how many samples we have processed. If the value of the
counter is less than the number of samples per cycle calculated
on line 135 then we can move to line 137 and increment the
counter (add 1 to the current value). If the counter value
is greater than the number of samples per cycle then we skip
to line 141 and reset the counter to 0 to start the count over.
On line 145 we calculate the tremolo modifying
value using equation 9 that we solved for in the design phase.
After calculating the modifier then we can apply it on lines
147 and 148 by multiplying the value of the “*in” sample by
the modifier and assigning the resultant to the “*out” pointer
which returns the value to the host.
The function for processReplacing() is
identical to process() except that we do not add
the output buffer to the input buffer before assigning it to
the output.
To
view the complete paper featuring the AGAIN walkthrough and
the TREMOLO plugin, plus mathematical derivations and more
detail, download this PDF file of my paper.
EA
Tremolo Paper.pdf |