-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSawAntiAlias.cpp
53 lines (43 loc) · 1.43 KB
/
SawAntiAlias.cpp
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
/* SawAntiAlias.cpp: implements sawtooth waveform generator class with reduced aliasing
* Sara Adkins
*/
#include <cmath>
#include "SawAntiAlias.h"
SawAntiAlias::SawAntiAlias(float sampleRate, float phaseOffset) {
setup(sampleRate, phaseOffset);
}
void SawAntiAlias::setup(float sampleRate, float phaseOffset)
{
// It's faster to multiply than to divide on most platforms, so we save the inverse
// of the sample rate for use in the phase calculation later
inverseSampleRate_ = 1.0 / sampleRate;
// used to scale output waveform based on f0
scalingFactor_ = sampleRate / 4.0f;
// Initialise the starting state
phase_ = phaseOffset;
z1_ = 1.0f;
}
// Set the oscillator frequency
void SawAntiAlias::setFrequency(float f) {
frequency_ = f;
}
// Get the oscillator frequency
float SawAntiAlias::getFrequency() {
return frequency_;
}
// Get the next sample and update the phase
float SawAntiAlias::process() {
float out = 0;
//Algorithm from Valimaki 2006
float bphase = phase_ * 2.0f - 1.0f; //convert [0,1] ramp to [-1,1]
float sqr_bphase = bphase * bphase; //turn sawtooth into parabolic waveform
out = (sqr_bphase - z1_); //differentiate
z1_ = sqr_bphase; //save state for next differentiation
out = out * scalingFactor_ / frequency_; //recover original amplitude by scaling by f0
// update and wrap phase
phase_ = phase_ + (inverseSampleRate_ * frequency_);
while(phase_ > 1.0f) {
phase_ -= 1.0f;
}
return out;
}