Skip to content

Commit 3b83a16

Browse files
author
Olivier Gillet
committed
Tides: polyblep for ramps
1 parent e1a75c6 commit 3b83a16

9 files changed

+252
-4600
lines changed

tides/generator.cc

+163-234
Large diffs are not rendered by default.

tides/generator.h

+67-41
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ struct GeneratorSample {
7070
uint8_t flags;
7171
};
7272

73-
const uint16_t kBlockSize = 16;
73+
const size_t kNumBlocks = 2;
74+
const size_t kBlockSize = 16;
7475

7576
struct FrequencyRatio {
7677
uint32_t p;
@@ -113,11 +114,6 @@ class Generator {
113114
}
114115

115116
void set_slope(int16_t slope) {
116-
#ifndef WAVETABLE_HACK
117-
if (range_ == GENERATOR_RANGE_HIGH) {
118-
CONSTRAIN(slope, -32512, 32512);
119-
}
120-
#endif // WAVETABLE_HACK
121117
slope_ = slope;
122118
}
123119

@@ -129,10 +125,6 @@ class Generator {
129125
frequency_ratio_ = ratio;
130126
}
131127

132-
void set_waveshaper_antialiasing(bool antialiasing) {
133-
antialiasing_ = antialiasing;
134-
}
135-
136128
void set_sync(bool sync) {
137129
if (!sync_ && sync) {
138130
pattern_predictor_.Init();
@@ -145,51 +137,56 @@ class Generator {
145137
inline GeneratorRange range() const { return range_; }
146138
inline bool sync() const { return sync_; }
147139

148-
inline GeneratorSample Process(uint8_t control) {
149-
input_buffer_.Overwrite(control);
150-
return output_buffer_.ImmediateRead();
140+
inline const GeneratorSample& Process(uint8_t control) {
141+
input_samples_[playback_block_][current_sample_] = control;
142+
const GeneratorSample& out = output_samples_[playback_block_][current_sample_];
143+
current_sample_ = current_sample_ + 1;
144+
if (current_sample_ >= kBlockSize) {
145+
current_sample_ = 0;
146+
playback_block_ = (playback_block_ + 1) % kNumBlocks;
147+
}
148+
return out;
151149
}
152150

153151
inline bool writable_block() const {
154-
return output_buffer_.writable() >= kBlockSize;
152+
return render_block_ != playback_block_;
155153
}
156154

157-
inline bool FillBufferSafe() {
158-
if (!writable_block()) {
159-
return false;
160-
} else {
161-
FillBuffer();
162-
return true;
155+
inline void Process() {
156+
while (render_block_ != playback_block_) {
157+
uint8_t* in = input_samples_[render_block_];
158+
GeneratorSample* out = output_samples_[render_block_];
159+
#ifndef WAVETABLE_HACK
160+
if (range_ == GENERATOR_RANGE_HIGH) {
161+
ProcessAudioRate(in, out, kBlockSize);
162+
} else {
163+
ProcessControlRate(in, out, kBlockSize);
164+
}
165+
ProcessFilterWavefolder(out, kBlockSize);
166+
#else
167+
ProcessWavetable(in, out, kBlockSize);
168+
#endif
169+
render_block_ = (render_block_ + 1) % kNumBlocks;
163170
}
164171
}
165172

166-
inline void FillBuffer() {
167-
#ifndef WAVETABLE_HACK
168-
if (range_ == GENERATOR_RANGE_HIGH) {
169-
FillBufferAudioRate();
170-
} else {
171-
FillBufferControlRate();
172-
}
173-
#else
174-
FillBufferWavetable();
175-
#endif
176-
}
177-
178173
uint32_t clock_divider() const {
179174
return clock_divider_;
180175
}
181176

182177
private:
183178
// There are two versions of the rendering code, one optimized for audio, with
184179
// band-limiting.
185-
void FillBufferAudioRate();
186-
void FillBufferControlRate();
187-
void FillBufferWavetable();
180+
void ProcessAudioRate(const uint8_t* in, GeneratorSample* out, size_t size);
181+
void ProcessControlRate(const uint8_t* in, GeneratorSample* out, size_t size);
182+
void ProcessWavetable(const uint8_t* in, GeneratorSample* out, size_t size);
183+
void ProcessFilterWavefolder(GeneratorSample* in_out, size_t size);
184+
188185
int32_t ComputeAntialiasAttenuation(
189186
int16_t pitch,
190187
int16_t slope,
191188
int16_t shape,
192-
int16_t smoothness);
189+
int16_t smoothness) const;
193190

194191
inline void ClearFilterState() {
195192
uni_lp_state_[0] = uni_lp_state_[1] = 0;
@@ -201,12 +198,37 @@ class Generator {
201198
int32_t ComputeCutoffFrequency(int16_t pitch, int16_t smoothness);
202199
void ComputeFrequencyRatio(int16_t pitch);
203200

204-
stmlib::RingBuffer<uint8_t, kBlockSize * 2> input_buffer_;
205-
stmlib::RingBuffer<GeneratorSample, kBlockSize * 2> output_buffer_;
206-
201+
inline int32_t NextIntegratedBlepSample(uint32_t t) const {
202+
if (t >= 65535) {
203+
t = 65535;
204+
}
205+
const int32_t t1 = t >> 1;
206+
const int32_t t2 = t1 * t1 >> 16;
207+
const int32_t t4 = t2 * t2 >> 16;
208+
return 12288 - t1 + (3 * t2 >> 1) - t4;
209+
}
210+
211+
inline int32_t ThisIntegratedBlepSample(uint32_t t) const {
212+
if (t >= 65535) {
213+
t = 65535;
214+
}
215+
t = 65535 - t;
216+
const int32_t t1 = t >> 1;
217+
const int32_t t2 = t1 * t1 >> 16;
218+
const int32_t t4 = t2 * t2 >> 16;
219+
return 12288 - t1 + (3 * t2 >> 1) - t4;
220+
}
221+
222+
GeneratorSample output_samples_[kNumBlocks][kBlockSize];
223+
uint8_t input_samples_[kNumBlocks][kBlockSize];
224+
size_t current_sample_;
225+
volatile size_t playback_block_;
226+
volatile size_t render_block_;
227+
207228
GeneratorMode mode_;
208229
GeneratorRange range_;
209230
GeneratorSample previous_sample_;
231+
GeneratorSample buffer_[kBlockSize];
210232

211233
uint32_t clock_divider_;
212234

@@ -217,11 +239,10 @@ class Generator {
217239
int16_t slope_;
218240
int32_t smoothed_slope_;
219241
int16_t smoothness_;
220-
bool antialiasing_;
242+
int16_t attenuation_;
221243

222244
uint32_t phase_;
223245
uint32_t phase_increment_;
224-
uint32_t sub_phase_;
225246
uint16_t x_;
226247
uint16_t y_;
227248
uint16_t z_;
@@ -245,6 +266,11 @@ class Generator {
245266

246267
bool running_;
247268

269+
// Polyblep status.
270+
int32_t next_sample_;
271+
bool slope_up_;
272+
uint32_t mid_point_;
273+
248274
static const FrequencyRatio frequency_ratios_[];
249275
static const int16_t num_frequency_ratios_;
250276

tides/makefile

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ TARGET = tides
4242
PACKAGES = tides tides/drivers stmlib/utils stmlib/system
4343
RESOURCES = tides/resources
4444

45+
TOOLCHAIN_PATH ?= /usr/local/arm-4.8.3/
46+
4547
include stmlib/makefile.inc
4648

4749
# Rule for building the firmware update file

0 commit comments

Comments
 (0)