From dd2faa4797c65949aaf98f2d8b176c95e72632f7 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Fri, 25 Jan 2019 13:08:36 +0100 Subject: [PATCH] Trying mod-delay-gain for Chorus effect. --- MicroMDAEPiano.ino | 94 ++++++++++++++++++++---------- mod-delay-gain.cpp | 141 +++++++++++++++++++++++++++++++++++++++++++++ mod-delay-gain.h | 93 ++++++++++++++++++++++++++++++ 3 files changed, 298 insertions(+), 30 deletions(-) create mode 100644 mod-delay-gain.cpp create mode 100644 mod-delay-gain.h diff --git a/MicroMDAEPiano.ino b/MicroMDAEPiano.ino index 5dc7013..f2027ee 100644 --- a/MicroMDAEPiano.ino +++ b/MicroMDAEPiano.ino @@ -28,6 +28,7 @@ #include #include #include +#include "mod-delay-gain.h" #include "mdaEPiano.h" #ifdef USE_XFADE_DATA #include "mdaEPianoDataXfade.h" @@ -59,29 +60,47 @@ AudioEffectFreeverb freeverb_r; AudioEffectFreeverb freeverb_l; AudioMixer4 mixer_r; AudioMixer4 mixer_l; +AudioSynthWaveform delaySweep_r; +AudioSynthWaveform envelope_r; +AudioSynthWaveform delaySweep_l; +AudioSynthWaveform envelope_l; +AudioEffectModDelayGain modulatedDelay_r; +AudioEffectModDelayGain modulatedDelay_l; AudioConnection patchCord0(queue_r, peak_r); AudioConnection patchCord1(queue_l, peak_l); AudioConnection patchCord4(queue_r, freeverb_r); AudioConnection patchCord5(queue_l, freeverb_l); -AudioConnection patchCord6(queue_r, 0, mixer_r, 0); -AudioConnection patchCord7(queue_l, 0, mixer_l, 0); -AudioConnection patchCord8(freeverb_r, 0, mixer_r, 1); -AudioConnection patchCord9(freeverb_l, 0, mixer_l, 1); +AudioConnection patchCord6(queue_r, modulatedDelay_r); +AudioConnection patchCord7(queue_l, modulatedDelay_l); +AudioConnection patchCord8(queue_r, 0, mixer_r, 0); +AudioConnection patchCord9(queue_l, 0, mixer_l, 0); +AudioConnection patchCord10(freeverb_r, 0, mixer_r, 1); +AudioConnection patchCord11(freeverb_l, 0, mixer_l, 1); +AudioConnection patchCord12(modulatedDelay_r, 0, mixer_r, 2); +AudioConnection patchCord13(modulatedDelay_l, 0, mixer_l, 2); +AudioConnection patchCord14(delaySweep_r, 0, modulatedDelay_r, 1); +AudioConnection patchCord15(delaySweep_l, 0, modulatedDelay_l, 1); +AudioConnection patchCord16(envelope_r, 0, modulatedDelay_r, 2); +AudioConnection patchCord17(envelope_l, 0, modulatedDelay_l, 2); #ifdef TEENSY_AUDIO_BOARD AudioOutputI2S i2s1; -AudioConnection patchCord110(mixer_r, 0, i2s1, 0); -AudioConnection patchCord111(mixer_l, 0, i2s1, 1); +AudioConnection patchCord18(mixer_r, 0, i2s1, 0); +AudioConnection patchCord19(mixer_l, 0, i2s1, 1); AudioControlSGTL5000 sgtl5000_1; #else AudioOutputPT8211 pt8211_1; AudioAmplifier volume_r; AudioAmplifier volume_l; -AudioConnection patchCord10(mixer_r, volume_r); -AudioConnection patchCord11(mixer_l, volume_l); -AudioConnection patchCord12(volume_r, 0, pt8211_1, 1); -AudioConnection patchCord13(volume_l, 0, pt8211_1, 0); +AudioConnection patchCord18(mixer_r, volume_r); +AudioConnection patchCord19(mixer_l, volume_l); +AudioConnection patchCord20(volume_r, 0, pt8211_1, 1); +AudioConnection patchCord21(volume_l, 0, pt8211_1, 0); #endif +const int32_t delayBufferLength = 4500; +int16_t delayBuf1[delayBufferLength]; +int16_t delayBuf2[delayBufferLength]; + // Objects mdaEPiano* ep; @@ -113,6 +132,7 @@ const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLE #ifdef SHOW_CPU_LOAD_MSEC elapsedMillis cpu_mem_millis; #endif +float modFreq = 2.0; enum MDA_EP_PARAM { DECAY, RELEASE, HARDNESS, TREBLE, PAN_TREM, LFO_RATE, VELOCITY_SENSE, STEREO, MAX_POLY, TUNE, DETUNE, OVERDRIVE }; @@ -127,26 +147,26 @@ void setup() Serial.begin(SERIAL_SPEED); delay(220); -/* - // LCD display setup - lcd.init(); - lcd.blink_off(); - lcd.cursor_off(); - lcd.backlight(); - lcd.noAutoscroll(); - lcd.clear(); - lcd.display(); - lcd.show(0, 0, 20, " MicroMDAEPiano"); - lcd.show(1, 0, 16, "(c)parasiTstudio"); - - // Encoder setup - enc[0].write(INITIAL_ENC_L_VALUE); - enc_val[0] = enc[0].read(); - enc[1].write(INITIAL_ENC_R_VALUE); - enc_val[1] = enc[1].read(); - but[0].update(); - but[1].update(); -*/ + /* + // LCD display setup + lcd.init(); + lcd.blink_off(); + lcd.cursor_off(); + lcd.backlight(); + lcd.noAutoscroll(); + lcd.clear(); + lcd.display(); + lcd.show(0, 0, 20, " MicroMDAEPiano"); + lcd.show(1, 0, 16, "(c)parasiTstudio"); + + // Encoder setup + enc[0].write(INITIAL_ENC_L_VALUE); + enc_val[0] = enc[0].read(); + enc[1].write(INITIAL_ENC_R_VALUE); + enc_val[1] = enc[1].read(); + but[0].update(); + but[1].update(); + */ // Debug output Serial.println(F("MicroMDAEPiano based on https://sourceforge.net/projects/mda-vst")); @@ -183,6 +203,8 @@ void setup() #endif // start audio card + AudioNoInterrupts(); + AudioMemory(AUDIO_MEM); #ifdef TEENSY_AUDIO_BOARD @@ -223,10 +245,22 @@ void setup() freeverb_l.roomsize(0.2); freeverb_r.damping(0.5); freeverb_l.damping(0.5); + + delaySweep_r.begin(1, modFreq, WAVEFORM_SINE); + delaySweep_l.begin(1, modFreq, WAVEFORM_SINE); + delaySweep_l.phase(180.0); + envelope_r.begin(1, modFreq, WAVEFORM_SINE); + envelope_l.begin(1, modFreq, WAVEFORM_SINE); + envelope_l.phase(180.0); + mixer_r.gain(0, 0.7); mixer_l.gain(0, 0.7); mixer_r.gain(1, 0.3); mixer_l.gain(1, 0.3); + mixer_r.gain(2, 0.5); + mixer_l.gain(2, 0.5); + + AudioInterrupts(); Serial.println(F("")); diff --git a/mod-delay-gain.cpp b/mod-delay-gain.cpp new file mode 100644 index 0000000..15be65b --- /dev/null +++ b/mod-delay-gain.cpp @@ -0,0 +1,141 @@ +/* Modulated delay line + + Inspired by; + http://musicdsp.org/showArchiveComment.php?ArchiveID=154 + + But details changed for Teensy Audio. + No feedback within the class, just done externally + so we can add filters and stuff to the loop. + + Delay time is a signal input to the block, and functions from 0 to 0x7fff, + scaling the delay time accordingly. +*/ +/* + Copyright (c) 2016, Byron Jacquot, SparkFun Electronics + SparkFun code, firmware, and software is released under + the MIT License(http://opensource.org/licenses/MIT). + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice, development funding notice, and this permission + notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + +*/ + + +#include "mod-delay-gain.h" + +#define INTERPOLATE (1) + +void AudioEffectModDelayGain::update(void) +{ + audio_block_t *audioblock, *controlblockDelay, *controlblockGain; + int16_t *data, *end, *ctrlDelay, *ctrlGain; + + int32_t extract_index; + int32_t temp; + +#ifdef INTERPOLATE + int32_t interp_delta; + int32_t next; + int16_t calc; +#endif + + if (buffer_length == 0) + return; + + audioblock = receiveWritable(0); + if (!audioblock) return; + + controlblockDelay = receiveReadOnly(1); + if (!controlblockDelay) { + release(audioblock); + return; + } + + controlblockGain = receiveReadOnly(2); + if (!controlblockGain) { + release(audioblock); + release(controlblockDelay); + return; + } + + data = audioblock->data; + end = audioblock->data + AUDIO_BLOCK_SAMPLES; + + ctrlDelay = controlblockDelay->data; + + ctrlGain = controlblockGain->data; + + do + { + delayline_p[insert_index] = *data; + insert_index++; + if (insert_index >= buffer_length) + { + insert_index = 0; + } + +#ifdef INTERPOLATE + // + interp_delta = (buffer_length * (*ctrlDelay)); + delay_delta = interp_delta >> 15; // MSB's for delay len + interp_delta &= 0x7fff; //LSBs for interp distance +#else + delay_delta = (buffer_length * (*ctrlDelay)) >> 15; +#endif + + extract_index = insert_index - delay_delta; + + if (extract_index < 0) + { + extract_index = buffer_length + extract_index; + } + +#ifdef INTERPOLATE + // Use the fractional part to interpolate between samples + next = extract_index + 1; + if (next >= buffer_length) + { + next = 0; + } + + calc = delayline_p[next] - delayline_p[extract_index]; + + calc = (calc * interp_delta ) >> 15; + calc += delayline_p[extract_index]; + + //*data = calc; + temp = (int32_t)calc * (*ctrlGain); + *data = temp >> 15; +#else + //data = delayline_p[extract_index]; + temp = (int32_t)delayline_p[extract_index] * (*ctrlGain); + *data = temp >> 15; +#endif + + data++; + ctrlDelay++; + ctrlGain++; + } while (data < end); + transmit(audioblock); + release(audioblock); + release(controlblockDelay); + release(controlblockGain); +} + + diff --git a/mod-delay-gain.h b/mod-delay-gain.h new file mode 100644 index 0000000..8bf474e --- /dev/null +++ b/mod-delay-gain.h @@ -0,0 +1,93 @@ +/* Modulated delay line + + Inspired by; + http://musicdsp.org/showArchiveComment.php?ArchiveID=154 + + But details changed for Teensy Audio. + No feedback within the class, just done externally + so we can add filters and stuff to the loop. + + Delay time is a signal input to the block, and functions from 0 to 0x7fff, + scaling the delay time accordingly. +*/ +/* + Copyright (c) 2016, Byron Jacquot, SparkFun Electronics + SparkFun code, firmware, and software is released under + the MIT License(http://opensource.org/licenses/MIT). + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice, development funding notice, and this permission + notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + +*/ + +/* from https://forum.pjrc.com/threads/46793-Anyone-Doing-Pitch-Shifting */ + +#pragma once + +#ifndef _mod_delay_h_ +#define _mod_delay_h_ + + +#include "AudioStream.h" +#include + +class AudioEffectModDelayGain: public AudioStream +{ + public: + AudioEffectModDelayGain (void) : AudioStream(3, inputQueueArray) + { + buffer_length = 0; + } + + virtual void update(void); + + // Set the parameters + void setbuf(int32_t delay_len, int16_t* delay_buf ) + { + delayline_p = delay_buf; + insert_index = 0; + buffer_length = delay_len; + + for (int32_t i = 0; i < buffer_length; i++) + { + delayline_p[i] = 0; + } + }; + + void inspect(void) + { + Serial.print(insert_index, HEX); + Serial.print(' '); + Serial.print(delay_delta, HEX); + Serial.print(' '); + Serial.println(buffer_length, HEX); + + }; + + private: + audio_block_t *inputQueueArray[3]; + + int16_t *delayline_p; + + int32_t insert_index; + int32_t buffer_length; + int32_t delay_delta; +}; + +#endif