-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoscillator.cpp
78 lines (62 loc) · 1.78 KB
/
oscillator.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
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
#include "oscillator.h"
#include "utility.h"
#include <math.h>
#include <stdlib.h>
#include <SDL.h>
namespace oscillator {
float Sine(float phase) {
return sin(phase);
}
float Square(float phase) {
return (phase < M_PI ? 1 : -1);
}
float Saw(float phase) {
return utility::Map(phase, 0.f, TWOPI, -1.f, 1.f);
}
float Triangle(float phase) {
if (phase < M_PI) {
return utility::Map(phase, 0.f, (float)M_PI, 1.f, -1.f);
} else {
return utility::Map(phase, (float)M_PI, TWOPI, -1.f, 1.f);
}
}
float Whitenoise(float phase) {
// phase unused
return utility::Map((float)rand(), 0.f, (float)RAND_MAX, -1.f, 1.f);
}
} // namespace oscillator
bool Oscillator::Init(Synth* synth) {
_synth = synth;
return true;
}
void Oscillator::Prev() {
_sourceIndex = (_sourceIndex == 0 ? _sources.size() - 1: _sourceIndex - 1);
}
void Oscillator::Next() {
_sourceIndex = (_sourceIndex + 1) % _sources.size();
}
// See this page for converting notes -> cents -> frequency
// https://en.wikipedia.org/wiki/Cent_(music)
float Oscillator::GetFrequency() const {
float cents = noteIndex * 100.0f;
cents += (round(coarsePitch) * 100.0f);
cents += finePitch;
return A0Freq * pow(2.f, cents / 1200.f);
}
void Oscillator::GetSample(float* left, float* right) {
float sample = _sources[_sourceIndex].fn(_phase);
// Update phase for next time
float dPhase = TWOPI * GetFrequency() / SAMPLE_RATE_HZ;
_phase = fmodf(_phase + dPhase, TWOPI);
if (!noteActive) {
*left = 0.0f;
*right = 0.0f;
return;
}
*left = sample * volume;
*right = sample * volume;
// Constant power panning
float theta = utility::Map(pan, -.5f, .5f, 0.f, (float)M_PI / 2.f);
*left *= cos(theta);
*right *= sin(theta);
}