-
Notifications
You must be signed in to change notification settings - Fork 0
/
VCO.h
114 lines (100 loc) · 2.73 KB
/
VCO.h
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#pragma once
#include "Common.h"
#include "FreqTable.h"
#include "WaveTable.h"
#include "WaveTable2.h"
template <uint8_t T>
class VCO
{
static const uint8_t** m_waveTables;
static uint8_t m_courseTune;
static uint8_t m_fineTune;
static uint8_t m_noteNumber;
static uint16_t m_phase;
static uint16_t m_freq;
public:
static void resetPhase()
{
m_phase = 0;
}
static void setWaveform(uint8_t waveform)
{
switch (waveform) {
case SAWTOOTH:
m_waveTables = g_waveTablesSawtooth;
break;
case SQUARE:
m_waveTables = g_waveTablesSquare;
break;
case TRIANGLE:
m_waveTables = g_waveTablesTriangle;
break;
case SINE:
m_waveTables = g_waveTablesSine;
break;
case PULSE_25:
m_waveTables = g_waveTablesPulse25;
break;
case PULSE_12:
m_waveTables = g_waveTablesPulse12;
break;
case PSEUDO_TRI:
m_waveTables = g_waveTablesPseudoTri;
break;
}
}
static void setCoarseTune(uint8_t coarseTune)
{
m_courseTune = coarseTune;
updateFreq();
}
static uint8_t coarseTune()
{
return m_courseTune;
}
static void setFineTune(uint8_t fineTune)
{
m_fineTune = fineTune;
updateFreq();
}
static void noteOn(uint8_t noteNumber)
{
m_noteNumber = noteNumber;
updateFreq();
}
static uint8_t clock()
{
m_phase += m_freq;
const uint8_t* waveTable = m_waveTables[highByte(m_freq)];
uint8_t currIndex = highByte(m_phase);
uint8_t nextIndex = currIndex + 1;
int8_t currData = pgm_read_byte(waveTable + currIndex);
int8_t nextData = pgm_read_byte(waveTable + nextIndex);
int8_t level;
uint8_t nextWeight = lowByte(m_phase);
if (nextWeight == 0) {
level = currData;
} else {
uint8_t currWeight = (uint8_t) 0 - nextWeight;
level = highByte((currData * currWeight) + (nextData * nextWeight));
}
return level;
}
static void updateFreq()
{
uint8_t noteNumber = m_noteNumber + m_courseTune - (uint8_t) 64;
if (m_fineTune <= (uint8_t) 63) {
m_freq = pgm_read_word(g_freqTableDetuneMinus + noteNumber);
} else if (m_fineTune == (uint8_t) 64) {
m_freq = pgm_read_word(g_freqTableDetuneNone + noteNumber);
} else {
m_freq = pgm_read_word(g_freqTableDetunePlus + noteNumber);
}
}
};
template <uint8_t T> const uint8_t** VCO<T>::m_waveTables = g_waveTablesSawtooth;
template <uint8_t T> uint8_t VCO<T>::m_courseTune = 64;
template <uint8_t T> uint8_t VCO<T>::m_fineTune = 64;
template <uint8_t T> uint8_t VCO<T>::m_noteNumber = 60;
template <uint8_t T> uint16_t VCO<T>::m_phase = 0;
template <uint8_t T> uint16_t VCO<T>::m_freq = 0;