WE Core
Loading...
Searching...
No Matches
RichterWavetables.h
Go to the documentation of this file.
1/*
2 * File: RichterWavetables.h
3 *
4 * Created: 13/07/2020
5 *
6 * This file is part of WECore.
7 *
8 * WECore is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * WECore is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with WECore. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
24#include "General/CoreMath.h"
25
26namespace WECore::Richter {
27
31 class Wavetables {
32 public:
33
37 static constexpr int SIZE {2000};
38
39 static const Wavetables* getInstance() {
40 static Wavetables instance;
41 return &instance;
42 }
43
44 const double* getSine() const { return _sineTable; }
45 const double* getSquare() const { return _squareTable; }
46 const double* getSaw() const { return _sawTable; }
47 const double* getSidechain() const { return _sidechainTable; }
48
49 private:
52 double _sawTable[SIZE];
54
58 inline Wavetables();
59 };
60
62
63 // Sine wavetable
64 for (int idx = 0; idx < Wavetables::SIZE; idx++) {
65 const double radians {idx * CoreMath::DOUBLE_TAU / Wavetables::SIZE};
66
67 // Just a conventional sine
68 _sineTable[idx] = sin(radians);
69 }
70
71 // Square wavetable
72 for (int idx = 0; idx < Wavetables::SIZE; idx++) {
73 const double radians {(idx * CoreMath::DOUBLE_TAU / Wavetables::SIZE) + 0.32};
74
75 // The fourier series for a square wave produces a very sharp square with some overshoot
76 // and ripple, so this actually uses slightly lower amplitudes for each harmonic than
77 // would normally be used.
78 //
79 // Because the harmonics are lower amplitude, it needs to be scaled up by 1.2 to reach
80 // a range of -1 to +1
81 _squareTable[idx] =
82 (
83 sin(radians) +
84 (0.3/1.0) * sin(3 * radians) +
85 (0.3/2.0) * sin(5 * radians) +
86 (0.3/4.0) * sin(7 * radians) +
87 (0.3/8.0) * sin(9 * radians) +
88 (0.3/16.0) * sin(11 * radians) +
89 (0.3/32.0) * sin(13 * radians)
90 ) * 1.2;
91 }
92
93 // Saw wavetable
94 for (int idx = 0; idx < Wavetables::SIZE; idx++) {
95 const double radians {(idx * CoreMath::DOUBLE_TAU / Wavetables::SIZE) + CoreMath::DOUBLE_PI};
96
97 // Conventional fourier series for a saw wave, scaled to fit -1 to 1
98 _sawTable[idx] =
99 (
100 sin(radians) -
101 (1.0/2.0) * sin(2 * radians) +
102 (1.0/3.0) * sin(3 * radians) -
103 (1.0/4.0) * sin(4 * radians) +
104 (1.0/6.0) * sin(5 * radians) -
105 (1.0/8.0) * sin(6 * radians) +
106 (1.0/12.0) * sin(7 * radians) -
107 (1.0/16.0) * sin(8 * radians) +
108 (1.0/24.0) * sin(9 * radians) -
109 (1.0/32.0) * sin(10 * radians) +
110 (1.0/48.0) * sin(11 * radians) -
111 (1.0/64.0) * sin(12 * radians) +
112 (1.0/96.0) * sin(13 * radians) -
113 (1.0/128.0) * sin(14 * radians)
114 ) * (2.0 / 3.0);
115 }
116
117 // Sidechain wavetable
118 for (int idx = 0; idx < Wavetables::SIZE; idx++) {
119 const double radians {idx * CoreMath::DOUBLE_TAU / Wavetables::SIZE};
120
121 _sidechainTable[idx] =
122 (
123 radians < 0.4497 ?
124 -2 * sin(pow(0.2 * radians - 0.8245, 6) * 10) + 1 :
125 -2 * sin(pow(0.15 * radians - 0.802, 6) * 10) + 1
126 );
127 }
128 }
129}
static const Wavetables * getInstance()
const double * getSidechain() const
const double * getSquare() const
const double * getSine() const
const double * getSaw() const
constexpr double DOUBLE_PI
Definition CoreMath.h:36
constexpr double DOUBLE_TAU
Definition CoreMath.h:39