From 3049a10b4b5f7c3b4b32f41a0d224b58abb6e4fa Mon Sep 17 00:00:00 2001 From: denizk0461 Date: Tue, 24 Sep 2024 17:37:50 +0200 Subject: [PATCH] Initial v1.0 push --- daisy.ino | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 daisy.ino diff --git a/daisy.ino b/daisy.ino new file mode 100644 index 0000000..2244eb6 --- /dev/null +++ b/daisy.ino @@ -0,0 +1,336 @@ +#include "DaisyDuino.h" +#include "math.h" + +#define PIN_A4 11 +#define PIN_AS4 14 +#define PIN_B4 10 +#define PIN_C5 9 +#define PIN_CS5 13 +#define PIN_D5 8 +#define PIN_DS5 12 +#define PIN_E5 7 +#define PIN_F5 3 +#define PIN_FS5 6 +#define PIN_G5 2 +#define PIN_GS5 5 +#define PIN_A5 1 +#define PIN_AS5 4 +#define PIN_B5 0 + +#define PIN_MUX_ADSR_A 16 +#define PIN_MUX_ADSR_B 17 +#define PIN_MUX_ADSR_C 18 +#define PIN_MUX_ADSR_ADC A8 + +#define PIN_MUX_ADSR_VOL_ATTACK 3 +#define PIN_MUX_ADSR_VOL_DECAY 0 +#define PIN_MUX_ADSR_VOL_SUSTAIN 1 +#define PIN_MUX_ADSR_VOL_RELEASE 2 +#define PIN_MUX_ADSR_FLT_ATTACK 5 +#define PIN_MUX_ADSR_FLT_DECAY 7 +#define PIN_MUX_ADSR_FLT_SUSTAIN 6 +#define PIN_MUX_ADSR_FLT_RELEASE 4 + +#define PIN_MUX_FM_A 20 +#define PIN_MUX_FM_B 21 +#define PIN_MUX_FM_C 22 +#define PIN_MUX_FM_ADC A4 + +#define PIN_MUX_FM_CAR_SIN 7 +#define PIN_MUX_FM_CAR_SQ 5 +#define PIN_MUX_FM_CAR_SAW 0 +#define PIN_MUX_FM_MOD_SIN 3 +#define PIN_MUX_FM_MOD_SQ 1 +#define PIN_MUX_FM_MOD_SAW 2 +#define PIN_MUX_FM_WET 4 +#define PIN_MUX_FM_DEV 6 + +#define PIN_VOL A9 +#define PIN_PITCH A11 + +#define PIN_FLT_Q A0 +#define PIN_FLT_SWITCH D25 + +#define ANALOG_MAX 1023.0 +#define FM_FREQ_MAX 120.0 + +DaisyHardware hw; + +size_t num_channels; +size_t sample_rate = 44000; + +Adsr volEnv; +Oscillator osc; + +float vol = 0.0; + +size_t key_count = 15; +int keys_pins[] = {PIN_A4, PIN_AS4, PIN_B4, PIN_C5, PIN_CS5, PIN_D5, PIN_DS5, PIN_E5, PIN_F5, PIN_FS5, PIN_G5, PIN_GS5, PIN_A5, PIN_AS5, PIN_B5}; +float keys_pitches[] = {440.0, 466.1638, 493.8833, 523.2511, 554.3653, 587.3295, 622.254, 659.2551, 698.4565, 739.9888, 783.9909, 830.6094, 880.0, 932.3275, 987.7666}; +bool keys_pressed[] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; +Adsr keys_adsr_vol[15]; +Adsr keys_adsr_flt[15]; +Oscillator keys_osc[15]; +Oscillator keys_osc_mod[15]; +Svf filters[15]; +Flanger flanger; +SampleRateReducer smp; +Overdrive dist; + +bool use_high_pass; + +float vol_adsr_attack; +float vol_adsr_decay; +float vol_adsr_sustain; +float vol_adsr_release; + +float mod_wet; +float mod_dev; +float dist_val; + +float pitch_dev; +float key_pitch; + +Limiter limiter; + +float adsr_max_seconds = 8.0; + +void Callback(float **in, float **out, size_t size) { + for (size_t i = 0; i < size; i += 1) { + float osc_out = 0.0; + float osc_result = 0.0; + float env_result = 0.0; + float flt_result = 0.0; + for (int k = 0; k < key_count; k += 1) { + // filters[k].SetFreq(1000); + + env_result = keys_adsr_vol[k].Process(keys_pressed[k]); + if (env_result == 0.0) { + // skip processing the oscillator if it wouldn't play a sound anyway to save on processing power + continue; + } + + keys_osc[k].SetAmp(env_result); + // osc_result = dist.Process(smp.Process(keys_osc[k].Process())); + osc_result = keys_osc[k].Process(); + // filters[k].Process(osc_result); + + if (mod_wet > 0.04) { + osc_result = (osc_result * (1 - mod_wet)) + ((osc_result * keys_osc_mod[k].Process()) * mod_wet); + } + + if (use_high_pass) { + osc_result = flanger.Process(osc_result); + } + + osc_result = smp.Process(osc_result); + + osc_result = ((osc_result * (dist_val - 1)) * -1) + dist.Process(osc_result); + + osc_out += osc_result; + } + + osc_out *= vol; + + limiter.ProcessBlock(&osc_out, 1, 1.0); + for (size_t chn = 0; chn < num_channels; chn++) { + out[chn][i] = osc_out; + } + } +} + +void setup() { + hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K); + num_channels = hw.num_channels; + sample_rate = DAISY.get_samplerate(); + + float sample_rate = DAISY.get_samplerate(); + Serial.begin(9600); + analogReadResolution(10); + + limiter.Init(); + + pinMode(PIN_MUX_ADSR_A, OUTPUT); + pinMode(PIN_MUX_ADSR_B, OUTPUT); + pinMode(PIN_MUX_ADSR_C, OUTPUT); + pinMode(PIN_MUX_FM_A, OUTPUT); + pinMode(PIN_MUX_FM_B, OUTPUT); + pinMode(PIN_MUX_FM_C, OUTPUT); + + pinMode(PIN_FLT_SWITCH, INPUT_PULLUP); + + for (int k = 0; k < key_count; k += 1) { + pinMode(keys_pins[k], INPUT_PULLUP); + keys_osc[k].Init(sample_rate); + keys_osc[k].SetWaveform(Oscillator::WAVE_SIN); + // keys_osc[k].SetFreq(keys_pitches[k]); + keys_osc[k].SetAmp(0.25); + + keys_osc_mod[k].Init(sample_rate); + keys_osc_mod[k].SetWaveform(Oscillator::WAVE_SIN); + // keys_osc_mod[k].SetFreq(keys_pitches[k]); + keys_osc_mod[k].SetAmp(0.25); + + keys_adsr_vol[k].Init(sample_rate); + keys_adsr_flt[k].Init(sample_rate); + + filters[k].Init(sample_rate); + // filters[k].SetFilterMode(FilterMode::LOW_PASS); + } + + flanger.Init(sample_rate); + smp.Init(); + dist.Init(); + + DAISY.begin(Callback); +} + +void loop() { + + vol_adsr_attack = (get_mux_adsr_value(PIN_MUX_ADSR_VOL_ATTACK) / ANALOG_MAX) * adsr_max_seconds; + vol_adsr_decay = (get_mux_adsr_value(PIN_MUX_ADSR_VOL_DECAY) / ANALOG_MAX) * adsr_max_seconds; + vol_adsr_sustain = get_mux_adsr_value(PIN_MUX_ADSR_VOL_SUSTAIN) / ANALOG_MAX; + vol_adsr_release = (get_mux_adsr_value(PIN_MUX_ADSR_VOL_RELEASE) / ANALOG_MAX) * adsr_max_seconds; + + // Modulator deviation + mod_dev = FM_FREQ_MAX * (((get_mux_fm_value(PIN_MUX_FM_DEV) / ANALOG_MAX) * 2.0) - 1.0); + + // Pitch control + pitch_dev = (((analogRead(PIN_PITCH) / ANALOG_MAX) * 24.0) - 12.0); + if (pitch_dev < 0.15 && pitch_dev > -0.15) { + pitch_dev = 0.0; + } + + for (int k = 0; k < key_count; k += 1) { + key_pitch = pow(pow(2.0, 1.0/12.0), (49.0 + k + pitch_dev) - (49.0)) * 440.0; + + // Played keys + keys_pressed[k] = digitalRead(keys_pins[k]) == 0; + + keys_osc[k].SetFreq(key_pitch); + keys_osc_mod[k].SetFreq(key_pitch); + + // Volume ADSR + keys_adsr_vol[k].SetTime(ADSR_SEG_ATTACK, vol_adsr_attack); + keys_adsr_vol[k].SetTime(ADSR_SEG_DECAY, vol_adsr_decay); + keys_adsr_vol[k].SetSustainLevel(vol_adsr_sustain); + keys_adsr_vol[k].SetTime(ADSR_SEG_RELEASE, vol_adsr_release); + + keys_osc_mod[k].SetFreq(keys_pitches[k] + mod_dev); + } + + // Volume control + vol = analogRead(PIN_VOL) / ANALOG_MAX; + + // Flanger + flanger.SetLfoFreq(get_mux_adsr_value(PIN_MUX_ADSR_FLT_ATTACK) / ANALOG_MAX); + flanger.SetLfoDepth(get_mux_adsr_value(PIN_MUX_ADSR_FLT_DECAY) / ANALOG_MAX); + flanger.SetDelay((analogRead(PIN_FLT_Q) / ANALOG_MAX) * 4.0); + + // Distortion + dist_val = get_mux_adsr_value(PIN_MUX_ADSR_FLT_SUSTAIN) / ANALOG_MAX; + dist.SetDrive(dist_val); + + // Sample Rate Reducer + smp.SetFreq(pow(get_mux_adsr_value(PIN_MUX_ADSR_FLT_RELEASE) / ANALOG_MAX, 2.0)); + + // Carrier waveform + if (get_mux_fm_button(PIN_MUX_FM_CAR_SIN) == 0) { + set_car_osc(Oscillator::WAVE_SIN); + } + if (get_mux_fm_button(PIN_MUX_FM_CAR_SQ) == 0) { + set_car_osc(Oscillator::WAVE_POLYBLEP_SQUARE); + } + if (get_mux_fm_button(PIN_MUX_FM_CAR_SAW) == 0) { + set_car_osc(Oscillator::WAVE_POLYBLEP_SAW); + } + + // Modulator waveform + if (get_mux_fm_button(PIN_MUX_FM_MOD_SIN) == 0) { + set_mod_osc(Oscillator::WAVE_SIN); + } + if (get_mux_fm_button(PIN_MUX_FM_MOD_SQ) == 0) { + set_mod_osc(Oscillator::WAVE_POLYBLEP_SQUARE); + } + if (get_mux_fm_button(PIN_MUX_FM_MOD_SAW) == 0) { + set_mod_osc(Oscillator::WAVE_POLYBLEP_SAW); + } + + // Modulator wet + mod_wet = get_mux_fm_value(PIN_MUX_FM_WET) / ANALOG_MAX; + + // Flanger on/off toggle + use_high_pass = digitalRead(PIN_FLT_SWITCH) == LOW; + + // Refresh 20 times per second + delay(50); +} + +float get_mux_adsr_value(int pin) { + int a = LOW; + int b = LOW; + int c = LOW; + if (pin % 2 != 0) { + a = HIGH; + } + if (pin == 2 || pin == 3 || pin > 5) { + b = HIGH; + } + if (pin > 3) { + c = HIGH; + } + digitalWrite(PIN_MUX_ADSR_A, a); + digitalWrite(PIN_MUX_ADSR_B, b); + digitalWrite(PIN_MUX_ADSR_C, c); + return analogRead(PIN_MUX_ADSR_ADC); +} + +float get_mux_fm_value(int pin) { + int a = LOW; + int b = LOW; + int c = LOW; + if (pin % 2 != 0) { + a = HIGH; + } + if (pin == 2 || pin == 3 || pin > 5) { + b = HIGH; + } + if (pin > 3) { + c = HIGH; + } + digitalWrite(PIN_MUX_FM_A, a); + digitalWrite(PIN_MUX_FM_B, b); + digitalWrite(PIN_MUX_FM_C, c); + return analogRead(PIN_MUX_FM_ADC); +} + +int get_mux_fm_button(int pin) { + int a = LOW; + int b = LOW; + int c = LOW; + if (pin % 2 != 0) { + a = HIGH; + } + if (pin == 2 || pin == 3 || pin > 5) { + b = HIGH; + } + if (pin > 3) { + c = HIGH; + } + digitalWrite(PIN_MUX_FM_A, a); + digitalWrite(PIN_MUX_FM_B, b); + digitalWrite(PIN_MUX_FM_C, c); + return analogRead(PIN_MUX_FM_ADC) < 0.1 ? 0 : 1; +} + +void set_car_osc(uint8_t waveform) { + for (int k = 0; k < key_count; k += 1) { + keys_osc[k].SetWaveform(waveform); + } +} + +void set_mod_osc(uint8_t waveform) { + for (int k = 0; k < key_count; k += 1) { + keys_osc_mod[k].SetWaveform(waveform); + } +} \ No newline at end of file