Compare commits

..

2 Commits

  1. 47
      Encoder4.h
  2. 86
      LiquidCrystalPlus_I2C.h
  3. 100
      MicroMDAEPiano.ino
  4. 3
      config.h
  5. 120
      mod-delay.cpp
  6. 89
      mod-delay.h

@ -0,0 +1,47 @@
/*
MicroMDAEPiano
MicroMDAEPiano is a port of the MDA-EPiano sound engine
(https://sourceforge.net/projects/mda-vst/) for the Teensy-3.5/3.6 with audio shield.
(c)2019 H. Wirtz <wirtz@parasitstudio.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Encoder.h>
#ifndef ENCODER4_H_INCLUDED
#define ENCODER4_H_INCLUDED
class Encoder4 : public Encoder
{
public:
using Encoder::Encoder;
int32_t read()
{
return (Encoder::read() / 4);
}
void write(int32_t p)
{
Encoder::write(p * 4);
}
};
#endif

@ -0,0 +1,86 @@
/*
MicroMDAEPiano
MicroMDAEPiano is a port of the MDA-EPiano sound engine
(https://sourceforge.net/projects/mda-vst/) for the Teensy-3.5/3.6 with audio shield.
(c)2019 H. Wirtz <wirtz@parasitstudio.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LIQUIDCRYSTALPLUS_I2C_H_INCLUDED
#define LIQUIDCRYSTALPLUS_I2C_H_INCLUDED
#include <LiquidCrystal_I2C.h> // https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
#define STRING_BUF_SIZE 21
class LiquidCrystalPlus_I2C : public LiquidCrystal_I2C
{
public:
using LiquidCrystal_I2C::LiquidCrystal_I2C;
void show(uint8_t y, uint8_t x, uint8_t fs, char *str)
{
_show(y, x, fs, str, false, false);
}
void show(uint8_t y, uint8_t x, uint8_t fs, long num)
{
char _buf10[STRING_BUF_SIZE];
_show(y, x, fs, itoa(num, _buf10, 10), true, true);
}
private:
void _show(uint8_t pos_y, uint8_t pos_x, uint8_t field_size, char *str, bool justify_right, bool fill_zero)
{
{
char tmp[STRING_BUF_SIZE];
char *s = tmp;
uint8_t l = strlen(str);
memset(tmp, 0, sizeof(tmp));
if (fill_zero == true)
memset(tmp, '0', field_size);
else
memset(tmp, 0x20, field_size - 1); // blank
if (l > field_size)
l = field_size;
if (justify_right == true)
s += field_size - l;
strncpy(s, str, l);
setCursor(pos_x, pos_y);
print(tmp);
#ifdef DEBUG
Serial.print(pos_y, DEC);
Serial.print(F("/"));
Serial.print(pos_x, DEC);
Serial.print(F(": ["));
Serial.print(tmp);
Serial.println(F("]"));
#endif
}
}
};
#endif

@ -28,8 +28,7 @@
#include <MIDI.h>
#include <EEPROM.h>
#include <limits.h>
#include <BALibrary.h>
#include <BAEffects.h>
#include "mod-delay.h"
#include "mdaEPiano.h"
#ifdef USE_XFADE_DATA
#include "mdaEPianoDataXfade.h"
@ -42,9 +41,10 @@
#ifdef MIDI_DEVICE_USB_HOST
#include <USBHost_t36.h>
#endif
using namespace BALibrary;
using namespace BAEffects;
#include <Bounce.h>
#include "Encoder4.h"
#include "LiquidCrystalPlus_I2C.h"
#include "UI.h"
//*************************************************************************************************
//* GLOBAL VARIABLES
@ -55,44 +55,41 @@ AudioPlayQueue queue_r;
AudioPlayQueue queue_l;
AudioAnalyzePeak peak_r;
AudioAnalyzePeak peak_l;
AudioEffectAnalogChorus analogChorus_r;
AudioEffectAnalogChorus analogChorus_l;
AudioEffectFreeverb freeverb_r;
AudioEffectFreeverb freeverb_l;
AudioMixer4 mixer_r;
AudioMixer4 mixer_l;
AudioSynthWaveform delaySweep_r;
AudioSynthWaveform delaySweep_l;
AudioEffectModDelay modulatedDelay_r;
AudioEffectModDelay modulatedDelay_l;
AudioConnection patchCord0(queue_r, peak_r);
AudioConnection patchCord1(queue_l, peak_l);
AudioConnection patchCord2(queue_r, analogChorus_r);
AudioConnection patchCord3(queue_l, analogChorus_l);
AudioConnection patchCord4(analogChorus_r, freeverb_r);
AudioConnection patchCord5(analogChorus_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 patchCord4(queue_r, freeverb_r);
AudioConnection patchCord5(queue_l, freeverb_l);
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);
#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;
#elif defined(TGA_BOARD)
BAAudioControlWM8731 codecControl;
AudioOutputI2S i2sOut;
AudioAmplifier volume_r;
AudioAmplifier volume_l;
AudioConnection patchCord10(mixer_r, volume_r);
AudioConnection patchCord11(mixer_l, volume_l);
AudioConnection patchCord12(volume_r, 0, i2sOut, 1);
AudioConnection patchCord13(volume_l, 0, i2sOut, 0);
#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
// Objects
@ -118,7 +115,7 @@ uint32_t xrun = 0;
uint32_t overload = 0;
uint32_t peak = 0;
uint16_t render_time_max = 0;
float vol = XVOLUME;
float vol = VOLUME;
float vol_right = 1.0;
float vol_left = 1.0;
elapsedMicros fill_audio_buffer;
@ -127,8 +124,12 @@ const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLE
elapsedMillis cpu_mem_millis;
#endif
enum MDA_EP_PARAM { DECAY, RELEASE, HARDNESS, TREBLE, PAN_TREM, LFO_RATE, VELOCITY_SENSE, STEREO, MAX_POLY, TUNE, DETUNE, OVERDRIVE };
const int32_t delayBufferLength = 1000;
int16_t delayBuf_r[delayBufferLength];
int16_t delayBuf_l[delayBufferLength];
float modFreq = 0.7;
enum MDA_EP_PARAM { DECAY, RELEASE, HARDNESS, TREBLE, PAN_TREM, LFO_RATE, VELOCITY_SENSE, STEREO, MAX_POLY, TUNE, DETUNE, OVERDRIVE };
//*************************************************************************************************
//* SETUP FUNCTION
@ -197,12 +198,6 @@ void setup()
// start audio card
AudioNoInterrupts();
#ifdef TGA_BOARD
codecControl.disable();
delay(100);
codecControl.enable();
delay(100);
#endif
AudioMemory(AUDIO_MEM);
@ -245,22 +240,19 @@ void setup()
freeverb_r.damping(0.5);
freeverb_l.damping(0.5);
analogChorus_r.enable();
analogChorus_r.bypass(true);
analogChorus_r.rate(0.2f);
analogChorus_r.mix(0.5f);
analogChorus_r.depth(0.4f);
analogChorus_l.enable();
analogChorus_l.bypass(true);
analogChorus_l.rate(0.2f);
analogChorus_l.mix(0.5f);
analogChorus_l.depth(0.4f);
mixer_r.gain(0, 0.7);
mixer_l.gain(0, 0.7);
mixer_r.gain(1, 0.3);
mixer_l.gain(1, 0.3);
modulatedDelay_r.setbuf(delayBufferLength, delayBuf_r);
modulatedDelay_l.setbuf(delayBufferLength, delayBuf_l);
delaySweep_r.begin(0.1, modFreq, WAVEFORM_SINE);
delaySweep_l.begin(0.1, modFreq, WAVEFORM_SINE);
//delaySweep_l.phase(180.0);
mixer_r.gain(0, 0.5);
mixer_l.gain(0, 0.5);
mixer_r.gain(1, 0.2);
mixer_l.gain(1, 0.2);
mixer_r.gain(2, 0.5);
mixer_l.gain(2, 0.5);
AudioInterrupts();
Serial.println(F("<setup end>"));

@ -40,7 +40,6 @@
// AUDIO
//#define TEENSY_AUDIO_BOARD 1
#define TGA_BOARD
//*************************************************************************************************
//* MIDI SETTINGS
@ -53,7 +52,7 @@
//* AUDIO SETTINGS
//*************************************************************************************************
#define XVOLUME 0.8
#define VOLUME 0.8
#define AUDIO_MEM 128
#define SAMPLE_RATE 44100
#define REDUCE_LOUDNESS 0

@ -0,0 +1,120 @@
/* 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.h"
#define INTERPOLATE (1)
void AudioEffectModDelay::update(void)
{
audio_block_t *audioblock, *controlblockDelay;
int16_t *data, *end, *ctrlDelay;
int32_t extract_index;
#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;
}
data = audioblock->data;
end = audioblock->data + AUDIO_BLOCK_SAMPLES;
ctrlDelay = controlblockDelay->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;
#else
*data = delayline_p[extract_index];
#endif
data++;
ctrlDelay++;
} while (data < end);
transmit(audioblock);
release(audioblock);
release(controlblockDelay);
}

@ -0,0 +1,89 @@
/* 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 <Arduino.h>
class AudioEffectModDelay: public AudioStream
{
public:
AudioEffectModDelay (void) : AudioStream(2, 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;
memset(delayline_p, 0, buffer_length);
};
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[2];
int16_t *delayline_p;
int32_t insert_index;
int32_t buffer_length;
int32_t delay_delta;
};
#endif
Loading…
Cancel
Save