Building Digital Guitar Effects - Using the Hothouse, Daisy Seed, STM32. Part 4 Delay and Reverb
CalSonics
0:00 / 0:00
Building Digital Guitar Effects - Using the Hothouse, Daisy Seed, STM32. Part 4 Delay and Reverb
447 просмотров · 1 мес. назад
CalSonics
4,38 тыс. подписчиков
447 просмотров · 1 мес. назад
In this tutorial I provide step-by-step instruction using the digital signal processing (DSP) principles needed to build delay and reverb pedals from scratch using the Daisy Seed microcontroller. The video starts by demonstrating how sample buffers and read/write pointers generate simple audio echoes, explores feedback behavior and comb filtering, and progresses to configuring series and parallel delay lines, used by David Gilmore and the Edge. I conclude by using an all-pass filter for phase dispersion, culminating in a functioning, 2112 style cave-like rudimentary reverb network
How to Add Daisy Support to Arduino IDE
• How to Add Daisy Support to Arduino IDE
Daisy Seed Setup and Install - Arduino, Daisy & STM32
• Daisy Seed Setup and Install - Arduino, Da...
Hothouse Schematic (pdf)
https://github.com/clevelandmusicco/o...
Hothouse GitHub
https://github.com/clevelandmusicco/H...
00:00 Introduction
00:11 How to code delay
01:07 Simple delay code review
03:31 Comb filter and All-pass filters
07:11 Stacking multiple delay code blocks in series
09:03 Stacking multiple delay code blocks in parallel
10:22 Turning delay into reverb
11:20 Phase dispersion and All-pass filters
13:10 Conclusion
References
Paper form Stanford
https://ccrma.stanford.edu/software/c...
Phils Lab (Best resource for STM32)
• Delay-Based Audio FX Software Implementati...
Sonic State - Algorithmic Reverb
• How It Works: Algorithmic Reverbs With Yoa...
Code examples (Replace GT & LT with greater or less than sign)
The complete digital reverb (play with his to create delays and reverbs)
#include "DaisyDuino.h"
static DaisyHardware hw;
#define MAX_DELAY_SAMPLES 48000
static float DSY_SDRAM_BSS buffer[MAX_DELAY_SAMPLES];
static float DSY_SDRAM_BSS buffer1[MAX_DELAY_SAMPLES]; // Second delay
static float DSY_SDRAM_BSS buffer2[MAX_DELAY_SAMPLES]; // Third delay
// Pointers and delay times
size_t write_ptr = 0;
size_t write_ptr1 = 0;
size_t write_ptr2 = 0;
// Change delay times here
size_t delay_samples = 1103; // ~22.98 ms (Prime)
size_t delay_samples1 = 1399; // ~29.15 ms (Prime)
size_t delay_samples2 = 241; // ~5.02 ms (Prime) // this is the APF
//Change the feedback (never exceed one, even 0.9 in the video was messy)
float feedback = 0.82f;
float feedback1 = 0.82f;
float feedback2 = 0.4f;
float mix = 0.3f;
void AudioCallback(float **in, float **out, size_t size) {
for (size_t i = 0; i LT size; i++) {
float dry_in = in[0][i];
// 1. Calculate read position wrapped to the buffer size
size_t read_ptr = (write_ptr + MAX_DELAY_SAMPLES - delay_samples) % MAX_DELAY_SAMPLES;
// 2. Read the delayed sample
float delayed_sample_val = buffer[read_ptr];
// 3. Write incoming audio + feedback into current buffer position
buffer[write_ptr] = dry_in + (delayed_sample_val * feedback);
// 4. Advance and wrap the write pointer
write_ptr = (write_ptr + 1) % MAX_DELAY_SAMPLES;
// And just do it again using the second buffer
float dry_in1 = in[0][i];
size_t read_ptr1 = (write_ptr1 + MAX_DELAY_SAMPLES - delay_samples1) % MAX_DELAY_SAMPLES;
float delayed_sample_val1 = buffer1[read_ptr1];
buffer1[write_ptr1] = dry_in1 + (delayed_sample_val1 * feedback1);
write_ptr1 = (write_ptr1 + 1) % MAX_DELAY_SAMPLES;
//Sum delay one and two
float early_sum = (delayed_sample_val + delayed_sample_val1) * 0.5f;
// set the read pointer
size_t read_ptr2 = (write_ptr2 + MAX_DELAY_SAMPLES - delay_samples2) % MAX_DELAY_SAMPLES;
float delayed_sample_val2 = buffer2[read_ptr2];
// Allpass
// Feedback
float ap_node = early_sum + (delayed_sample_val2 * feedback2);
buffer2[write_ptr2] = ap_node;
write_ptr2 = (write_ptr2 + 1) % MAX_DELAY_SAMPLES;
//Feed forward
float wet_mix = delayed_sample_val2 - (feedback2 * ap_node);
// Master Dry / Wet mix
float output_sample = (dry_in * (1.0f - (mix))) + (wet_mix * (mix));
out[0][i] = output_sample;
out[1][i] = output_sample;
}
}
void setup() {
hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K);
// Clear SDRAM buffer to prevent startup noise
for (size_t i = 0; i LT MAX_DELAY_SAMPLES; i++) {
buffer[i] = 0.0f;
buffer1[i] = 0.0f;
buffer2[i] = 0.0f;
}
DAISY.begin(AudioCallback);
}
void loop() {}