From 8d5828a20e74e8da4b2036cc902738cae3c4cd01 Mon Sep 17 00:00:00 2001 From: David Huss <dh@atoav.com> Date: Mon, 4 Dec 2023 16:51:20 +0100 Subject: [PATCH] Refactor + Looper now persists loop-Points --- code/daisy-looper/helpers.h | 1 - code/daisy-looper/looper.h | 5 + code/daisy-looper/ui.h | 315 +++++++++--------- code/rgb_led_envelope_follower/env_follower.h | 91 ----- code/rgb_led_envelope_follower/leds.h | 60 ---- .../rgb_led_envelope_follower.ino | 61 ---- 6 files changed, 167 insertions(+), 366 deletions(-) delete mode 100644 code/rgb_led_envelope_follower/env_follower.h delete mode 100644 code/rgb_led_envelope_follower/leds.h delete mode 100644 code/rgb_led_envelope_follower/rgb_led_envelope_follower.ino diff --git a/code/daisy-looper/helpers.h b/code/daisy-looper/helpers.h index 973bbe4..964bfa3 100644 --- a/code/daisy-looper/helpers.h +++ b/code/daisy-looper/helpers.h @@ -139,5 +139,4 @@ int button_multi(const char *buf, int x, int y, int color, int underline_line=0, return w; } - #endif \ No newline at end of file diff --git a/code/daisy-looper/looper.h b/code/daisy-looper/looper.h index fc3231d..22a8804 100644 --- a/code/daisy-looper/looper.h +++ b/code/daisy-looper/looper.h @@ -59,6 +59,7 @@ class Looper { void SetLoop(const float loop_start_time, const float loop_length_time) { if (!isnan(loop_start_time)) { + loop_start_f = loop_start_time; // Set the start of the next loop pending_loop_start = static_cast<size_t>(loop_start_time * (buffer_length - 1)); @@ -67,6 +68,7 @@ class Looper { } if (!isnan(loop_length_time)) { + loop_length_f = loop_length_time; // Set the length of the next loop pendingloop_length = max(kMinLoopLength, static_cast<size_t>(loop_length_time * buffer_length)); @@ -246,6 +248,9 @@ class Looper { rec_start_mode = mode; } + float loop_length_f = 1.0f; + float loop_start_f = 0.0f; + private: static const size_t kFadeLength = 200; static const size_t kMinLoopLength = 2 * kFadeLength; diff --git a/code/daisy-looper/ui.h b/code/daisy-looper/ui.h index 523842a..af65c5b 100644 --- a/code/daisy-looper/ui.h +++ b/code/daisy-looper/ui.h @@ -11,7 +11,7 @@ #include "looper.h" #include "button_grid.h" -#define UI_MAX_FPS 60 +#define UI_MAX_FPS 10 #define WAVEFORM_OVERSAMPLING 2 #define WAVEFORM_LIN true @@ -182,45 +182,42 @@ class Ui { // Except for the splash screen this is expected to be called // repeatedly in a loop void Render() { - switch (ui_mode) { - case UI_MODE_SPLASH: - renderSplash(); - break; - case UI_MODE_DEFAULT: - setupDefault(); - renderDefault(); - break; - case UI_MODE_REC_MENU: - setupRecMenu(); - renderGrid(0, rec_mode); - break; - case UI_MODE_PLAY_MENU: - setupPlayMenu(); - renderGrid(1); - break; - case UI_MODE_TRIGGER_MENU: - renderGrid(2); - break; - case UI_MODE_FX_MENU: - renderGrid(3); - break; - case UI_MODE_BUFFER_MENU: - setupBufferMenu(); - renderGrid(4, active_buffer); - break; + double now = millis(); + // Serial.println(1000.0/UI_MAX_FPS); + if ((now - last_render) > (1000.0/UI_MAX_FPS)) { + switch (ui_mode) { + case UI_MODE_SPLASH: + renderSplash(); + break; + case UI_MODE_DEFAULT: + renderDefault(); + break; + case UI_MODE_REC_MENU: + renderGrid(0, rec_mode); + break; + case UI_MODE_PLAY_MENU: + renderGrid(1); + break; + case UI_MODE_TRIGGER_MENU: + renderGrid(2); + break; + case UI_MODE_FX_MENU: + renderGrid(3); + break; + case UI_MODE_BUFFER_MENU: + renderGrid(4, active_buffer); + break; + } + last_render = now; } } // Helper method to render a certain button grid void renderGrid(size_t num, int button_enum=0) { - double now = millis(); - if (now - last_render > (1000.0/UI_MAX_FPS)) { - display.clearDisplay(); - button_grids[num].render(button_enum); - // Display all that stuff and store the time of the last render - display.display(); - last_render = now; - } + display.clearDisplay(); + button_grids[num].render(button_enum); + // Display all that stuff and store the time of the last render + display.display(); } // Renders a splash screen (runs once) @@ -503,127 +500,121 @@ class Ui { void renderDefault() { // Store the current time and check how long ago the last frame was // in ms - double now = millis(); - if (now - last_render > (1000.0/UI_MAX_FPS)) { - - // Clear the display - display.clearDisplay(); + + // Clear the display + display.clearDisplay(); + + // Waveform should be maximum screen-heigh + int wave_height = display.height() * 1.0f; + // Ensure that when stepping from left to right we fit the waveform on the screen + int step = activeLooper()->getBufferLength() / (display.width() * WAVEFORM_OVERSAMPLING); + // Helper variable for the bottom of the screen + int bottom = display.height()-1; + + // Render the waveform by iterating through the samples (oversampled by a factor + // defined on top of this file). Average the samples for each pixel of the 128 px + // wide screen and cache the resulting heights so we only have to recalculate when + // the waveform changes + for (int i=0; i<display.width()*WAVEFORM_OVERSAMPLING; i+=WAVEFORM_OVERSAMPLING) { + uint16_t x = int(i / WAVEFORM_OVERSAMPLING); + // Only recalculate if the cahce is dirty, else use cache + if (waveform_cache_dirty) { + float sig = 0.0f; + float scale = 1.0f; + if (!WAVEFORM_LIN) { + scale = 10.0f; + } + // Step through the buffer and sum the absolute values + for (int s=0; s<WAVEFORM_OVERSAMPLING; s++) { + float abs_sig = activeLooper()->getBuffer()[step*i]; + abs_sig = abs(abs_sig) * scale; + sig += abs_sig; + } + // We oversampled so divide here + sig = sig / float(WAVEFORM_OVERSAMPLING); - // Waveform should be maximum screen-heigh - int wave_height = display.height() * 1.0f; - // Ensure that when stepping from left to right we fit the waveform on the screen - int step = activeLooper()->getBufferLength() / (display.width() * WAVEFORM_OVERSAMPLING); - // Helper variable for the bottom of the screen - int bottom = display.height()-1; - - // Render the waveform by iterating through the samples (oversampled by a factor - // defined on top of this file). Average the samples for each pixel of the 128 px - // wide screen and cache the resulting heights so we only have to recalculate when - // the waveform changes - for (int i=0; i<display.width()*WAVEFORM_OVERSAMPLING; i+=WAVEFORM_OVERSAMPLING) { - uint16_t x = int(i / WAVEFORM_OVERSAMPLING); - // Only recalculate if the cahce is dirty, else use cache - if (waveform_cache_dirty) { - float sig = 0.0f; - float scale = 1.0f; - if (!WAVEFORM_LIN) { - scale = 10.0f; + if (!WAVEFORM_LIN) { + // Volume is logarithmic (hiding silent noises) + if (sig != 0.0f) { + sig = log10(sig); } - // Step through the buffer and sum the absolute values - for (int s=0; s<WAVEFORM_OVERSAMPLING; s++) { - float abs_sig = activeLooper()->getBuffer()[step*i]; - abs_sig = abs(abs_sig) * scale; - sig += abs_sig; - } - // We oversampled so divide here - sig = sig / float(WAVEFORM_OVERSAMPLING); - - if (!WAVEFORM_LIN) { - // Volume is logarithmic (hiding silent noises) - if (sig != 0.0f) { - sig = log10(sig); - } - } - waveform_cache[x] = int(sig * wave_height); } - - // Draw the vertical lines from bottom up, depending on the level of the - // calulcated wave on this point of the screen - display.drawFastVLine(x, bottom, -waveform_cache[x], SH110X_WHITE); - - } - // Draw one horizontal line on bottom - display.drawFastHLine(0, bottom, display.width(), SH110X_WHITE); - - // Cache is now marked as clean - waveform_cache_dirty = false; - - // Draw Indicator for loop start - int x_start_loop = int(loop_start * display.width()); - display.drawLine(x_start_loop, 0, x_start_loop, bottom, SH110X_WHITE); - display.fillTriangle(x_start_loop, 6, x_start_loop, 0, x_start_loop+3, 0, SH110X_WHITE); - - // Draw Indicator for Loop End - int x_loop_length = int(loop_length * display.width()); - int x_loop_end = (x_start_loop + x_loop_length) % display.width(); - display.drawLine(x_loop_end, 0, x_loop_end, bottom, SH110X_WHITE); - display.fillTriangle(x_loop_end, 6, x_loop_end-3, 0, x_loop_end, 0, SH110X_WHITE); - - // Draw connecting line for start and end - if (x_loop_end >= x_start_loop) { - display.drawLine(x_start_loop, 0, x_loop_end, 0, SH110X_WHITE); - } else { - display.drawLine(x_start_loop, 0, display.width(), 0, SH110X_WHITE); - display.drawLine(0, 0, x_loop_end, 0, SH110X_WHITE); - } - - // Draw Playhead - int x_playhead = int(activeLooper()->GetPlayhead() * display.width()) + x_start_loop; - display.drawLine(x_playhead, 6, x_playhead, 24, SH110X_WHITE); - - // Draw Recording Indicator and Recording Head - if (recording_state == REC_STATE_RECORDING) { - // Draw Rec Head - int x_rec_head = int(activeLooper()->GetRecHead() * display.width()); - display.drawLine(x_rec_head, 10, x_rec_head, bottom, SH110X_WHITE); - display.fillCircle(x_rec_head, 10, 3, SH110X_WHITE); - // Record sign - display.fillRect(0, 0, 13, 13, SH110X_WHITE); - display.fillRect(2, 2, 12, 12, SH110X_WHITE); - display.fillRect(1, 1, 11, 11, SH110X_BLACK); - display.fillCircle(6, 6, 3, SH110X_WHITE); - } - - // Draw Overdub Indicator and Recording Head - if (recording_state == REC_STATE_OVERDUBBING) { - // Draw Rec Head - int x_rec_head = int(activeLooper()->GetRecHead() * display.width()); - display.drawLine(x_rec_head, 10, x_rec_head, bottom, SH110X_WHITE); - display.fillCircle(x_rec_head, 10, 3, SH110X_WHITE); - - // Overdub sign (a "plus") - display.fillRect(0, 0, 13, 13, SH110X_WHITE); - display.fillRect(2, 2, 12, 12, SH110X_WHITE); - display.fillRect(1, 1, 11, 11, SH110X_BLACK); - display.drawLine(6, 2, 6, 10, SH110X_WHITE); - display.drawLine(2, 6, 10, 6, SH110X_WHITE); + waveform_cache[x] = int(sig * wave_height); } - // Render potentiometer UIs in case a knob is changed - pot_1.renderUi(); - pot_2.renderUi(); - pot_3.renderUi(); - pot_4.renderUi(); - pot_5.renderUi(); - pot_6.renderUi(); - pot_7.renderUi(); + // Draw the vertical lines from bottom up, depending on the level of the + // calulcated wave on this point of the screen + display.drawFastVLine(x, bottom, -waveform_cache[x], SH110X_WHITE); + + } + // Draw one horizontal line on bottom + display.drawFastHLine(0, bottom, display.width(), SH110X_WHITE); + + // Cache is now marked as clean + waveform_cache_dirty = false; + + // Draw Indicator for loop start + int x_start_loop = int(activeLooper()->loop_start_f * display.width()); + display.drawLine(x_start_loop, 0, x_start_loop, bottom, SH110X_WHITE); + display.fillTriangle(x_start_loop, 6, x_start_loop, 0, x_start_loop+3, 0, SH110X_WHITE); + + // Draw Indicator for Loop End + int x_loop_length = int(activeLooper()->loop_length_f * display.width()); + int x_loop_end = (x_start_loop + x_loop_length) % display.width(); + display.drawLine(x_loop_end, 0, x_loop_end, bottom, SH110X_WHITE); + display.fillTriangle(x_loop_end, 6, x_loop_end-3, 0, x_loop_end, 0, SH110X_WHITE); + + // Draw connecting line for start and end + if (x_loop_end >= x_start_loop) { + display.drawLine(x_start_loop, 0, x_loop_end, 0, SH110X_WHITE); + } else { + display.drawLine(x_start_loop, 0, display.width(), 0, SH110X_WHITE); + display.drawLine(0, 0, x_loop_end, 0, SH110X_WHITE); + } - // Display all the things done above - display.display(); + // Draw Playhead + int x_playhead = int(activeLooper()->GetPlayhead() * display.width()) + x_start_loop; + display.drawLine(x_playhead, 6, x_playhead, 24, SH110X_WHITE); + + // Draw Recording Indicator and Recording Head + if (recording_state == REC_STATE_RECORDING) { + // Draw Rec Head + int x_rec_head = int(activeLooper()->GetRecHead() * display.width()); + display.drawLine(x_rec_head, 10, x_rec_head, bottom, SH110X_WHITE); + display.fillCircle(x_rec_head, 10, 3, SH110X_WHITE); + // Record sign + display.fillRect(0, 0, 13, 13, SH110X_WHITE); + display.fillRect(2, 2, 12, 12, SH110X_WHITE); + display.fillRect(1, 1, 11, 11, SH110X_BLACK); + display.fillCircle(6, 6, 3, SH110X_WHITE); + } - // Store the time of when we started rendering - last_render = now; + // Draw Overdub Indicator and Recording Head + if (recording_state == REC_STATE_OVERDUBBING) { + // Draw Rec Head + int x_rec_head = int(activeLooper()->GetRecHead() * display.width()); + display.drawLine(x_rec_head, 10, x_rec_head, bottom, SH110X_WHITE); + display.fillCircle(x_rec_head, 10, 3, SH110X_WHITE); + + // Overdub sign (a "plus") + display.fillRect(0, 0, 13, 13, SH110X_WHITE); + display.fillRect(2, 2, 12, 12, SH110X_WHITE); + display.fillRect(1, 1, 11, 11, SH110X_BLACK); + display.drawLine(6, 2, 6, 10, SH110X_WHITE); + display.drawLine(2, 6, 10, 6, SH110X_WHITE); } + + // Render potentiometer UIs in case a knob is changed + pot_1.renderUi(); + pot_2.renderUi(); + pot_3.renderUi(); + pot_4.renderUi(); + pot_5.renderUi(); + pot_6.renderUi(); + pot_7.renderUi(); + + // Display all the things done above + display.display(); } // Activate recording and set the waveform cache to dirty @@ -692,8 +683,30 @@ class Ui { // Update the Ui variables (expected to run repeatedly) void update() { resetRecordingState(); + + switch (ui_mode) { + case UI_MODE_SPLASH: + break; + case UI_MODE_DEFAULT: + setupDefault(); + break; + case UI_MODE_REC_MENU: + setupRecMenu(); + break; + case UI_MODE_PLAY_MENU: + setupPlayMenu(); + break; + case UI_MODE_TRIGGER_MENU: + break; + case UI_MODE_FX_MENU: + break; + case UI_MODE_BUFFER_MENU: + setupBufferMenu(); + break; + } } + // Returns a pointer to the currently active looper atoav::Looper * activeLooper() { switch(active_buffer) { case ACTIVE_BUFFER_A: { @@ -729,20 +742,16 @@ class Ui { // Set the Looper start/length to a given value void setLoop(float start, float length) { - loop_start = start; - loop_length = length; activeLooper()->SetLoop(start, length); } private: - double last_render; + double last_render = 0.0; uint16_t waveform_cache[128] = {0}; bool waveform_cache_dirty = true; RecordingState recording_state = REC_STATE_NOT_RECORDING; UiMode last_ui_mode = UI_MODE_LAST; bool rec_button_momentary = true; - float loop_start = 0.0f; - float loop_length = 0.0f; }; diff --git a/code/rgb_led_envelope_follower/env_follower.h b/code/rgb_led_envelope_follower/env_follower.h deleted file mode 100644 index b3a1239..0000000 --- a/code/rgb_led_envelope_follower/env_follower.h +++ /dev/null @@ -1,91 +0,0 @@ -#include "wiring_constants.h" -#ifndef Env_follower_h -#define Env_follower_h -#include "Arduino.h" - -namespace atoav { - -class SmoothingFilter { - public: - void Init(float smoothing_time_ms, float sample_rate) { - a = exp(-TWO_PI / (smoothing_time_ms * 0.001f * sample_rate)); - b = 1.0f - a; - z = 0.0f; - } - - inline float Process(float in) { - z = (in * b) + (z * a); - return z; - } - - void setSmoothing(float smoothing_time_ms, float sample_rate) { - a = exp(-TWO_PI / (smoothing_time_ms * 0.001f * sample_rate)); - b = 1.0f - a; - } - - private: - float a; - float b; - float z; -}; - - -class EnvelopeFollower { - public: - void Init(float sample_rate) { - sample_rate = sample_rate; - attack = 200.0f; - decay = 4000.0f; - smoothing = 50.0f; - value = 0.0f; - smoothing_filter.Init(smoothing, sample_rate); - } - - void SetAttack(float attack_ms) { - attack = pow(0.01, 1.0 / (attack_ms * sample_rate * 0.001)); - } - - void SetDecay(float decay_ms) { - decay = pow(0.01, 1.0 / (decay_ms * sample_rate * 0.001)); - } - - void SetSmoothing(float smoothing_ms) { - smoothing_filter.setSmoothing(smoothing_ms, sample_rate); - } - - float Process(float in) { - abs_value = smoothing_filter.Process(abs(in)); - if (abs_value > value) { - value = attack * (value - abs_value) + abs_value; - } else { - value = decay * (value - abs_value) + abs_value; - } - return value; - } - - float value; - - float getValue() { - if (value == 0.0f || value == -0.0f) { - return value; - } - return max(0.0f, (3.0f + log10(value)) / 3.0f); - // return value; - } - - - private: - float sample_rate; - float attack; - float decay; - float smoothing; - float abs_value = 0.0f; - SmoothingFilter smoothing_filter; -}; -}; - - - - - -#endif \ No newline at end of file diff --git a/code/rgb_led_envelope_follower/leds.h b/code/rgb_led_envelope_follower/leds.h deleted file mode 100644 index 30f740b..0000000 --- a/code/rgb_led_envelope_follower/leds.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef Leds_h -#define Leds_h -#include "Arduino.h" - - -// Lookup Table for Red LED Channel -int red_lookup[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 25, 27, 28, 31, 33, 37, 40, 45, 50, 56, 63, 70, 78, 88, 98, 109, 122, 135, 150, 166, 183, 202, 222, 243, 255, 255, 255, 255, 255}; - -// Lookup Table for Green LED Channel -int green_lookup[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40, 42, 43, 43, 43, 42, 42, 42, 42, 41, 41, 41, 41, 41, 40, 40, 40, 40, 39, 39, 39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 26, 26, 25, 25, 25, 25, 24, 24, 24, 24, 24, 23, 23, 23, 23, 22, 22, 22, 22, 21, 21, 21, 21, 21, 20, 20, 20, 20, 19, 19, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 8}; - -// Lookup Table for Blue LED Channel -int blue_lookup[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -class RGBLed { - int pin_red; - int pin_green; - int pin_blue; - - public: - RGBLed(int pin_red, int pin_green, int pin_blue); - void init(); - void off(); - void setColor(int r, int g, int b); - void setAudioLevelIndicator(int level); -}; - -RGBLed::RGBLed(int pin_red, int pin_green, int pin_blue) { - this->pin_red = pin_red; - this->pin_green = pin_green; - this->pin_blue = pin_blue; -} - -void RGBLed::init() { - pinMode(this->pin_red, OUTPUT); - pinMode(this->pin_green, OUTPUT); - pinMode(this->pin_blue, OUTPUT); -} - -void RGBLed::off() { - digitalWrite(this->pin_red, LOW); - digitalWrite(this->pin_green, LOW); - digitalWrite(this->pin_blue, LOW); -} - -void RGBLed::setColor(int r, int g, int b) { - r = min(255, max(0, r)); - g = min(255, max(0, g)); - b = min(255, max(0, b)); - analogWrite(this->pin_red, r); - analogWrite(this->pin_green, g); - analogWrite(this->pin_blue, b); -} - -void RGBLed::setAudioLevelIndicator(int level) { - level = min(255, max(0, level)); - this->setColor(red_lookup[level], green_lookup[level], blue_lookup[level]); -} - -#endif \ No newline at end of file diff --git a/code/rgb_led_envelope_follower/rgb_led_envelope_follower.ino b/code/rgb_led_envelope_follower/rgb_led_envelope_follower.ino deleted file mode 100644 index ec87671..0000000 --- a/code/rgb_led_envelope_follower/rgb_led_envelope_follower.ino +++ /dev/null @@ -1,61 +0,0 @@ -// Title: Envelope Follower -// Description: Drives an RGB-LED from an Envelope follower -// Hardware: Daisy Seed -// Author: David Huss - -#include "DaisyDuino.h" -#include "env_follower.h" -#include "leds.h" - -DaisyHardware hw; - -// Create an instance of the envelope folower -atoav::EnvelopeFollower envelope_follower; - - -// LED R G B -RGBLed rgb_led = RGBLed(A10, A9, A11); - -size_t num_channels; - - - -void AudioCallback(float **in, float **out, size_t size) { - for (size_t i = 0; i < size; i++) { - // Generate the envelope (only use channel 2) - envelope_follower.Process(in[1][i]); - // Input goes directly to output - for (size_t chn = 0; chn < num_channels; chn++) { - out[chn][i] = in[chn][i]; - } - } -} - -void setup() { - float samplerate; - // Initialize for Daisy pod at 48kHz - hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K); - - // Initialize some variables - num_channels = hw.num_channels; - samplerate = DAISY.get_samplerate(); - - // Initialize the Envelope follower - envelope_follower.Init(samplerate); - envelope_follower.SetAttack(50.0); - envelope_follower.SetDecay(200.0); - - - - DAISY.begin(AudioCallback); - rgb_led.init(); - Serial.begin(250000); -} - -void loop() { - // Get the value from the envelope - float envelope_reading = envelope_follower.getValue(); - - // Set the brightness and Color of the LED depending on the envelope - rgb_led.setAudioLevelIndicator(int(envelope_reading * 255)); -} -- GitLab