commit
0a38957623
@ -0,0 +1,285 @@ |
||||
// Minimoog
|
||||
/*
|
||||
* This program is part of a minimoog-like synthesizer based on teensy 4.0 |
||||
* Copyright (C) 2020 Pierre-Loup Martin |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/* This program is a synthesizer very similar to the minimoog model D.
|
||||
* It is intended to run on a Teensy 4.0, using the PJRC audio library. |
||||
* It also uses two Arduino Mega boards to manage all the user inputs : |
||||
* keyboard, switches, potentiometers, etc. |
||||
* All user inputs are handled and send to the teensy board using midi commands |
||||
*/ |
||||
|
||||
#define CC0 0 |
||||
#define CC1 1 |
||||
#define CC2 2 |
||||
#define CC3 3 |
||||
#define CC4 4 |
||||
#define CC5 5 |
||||
#define CC6 6 |
||||
#define CC7 7 |
||||
#define CC8 8 |
||||
#define CC9 9 |
||||
#define CC10 10 |
||||
#define CC11 11 |
||||
#define CC12 12 |
||||
#define CC13 13 |
||||
#define CC14 14 |
||||
#define CC15 15 |
||||
#define CC16 16 |
||||
#define CC17 17 |
||||
#define CC18 18 |
||||
#define CC19 19 |
||||
#define CC20 20 |
||||
#define CC21 21 |
||||
#define CC22 22 |
||||
#define CC23 23 |
||||
#define CC24 24 |
||||
#define CC25 25 |
||||
#define CC26 26 |
||||
#define CC27 27 |
||||
#define CC28 28 |
||||
#define CC29 29 |
||||
#define CC30 30 |
||||
#define CC31 31 |
||||
#define CC32 32 |
||||
#define CC33 33 |
||||
#define CC34 34 |
||||
#define CC35 35 |
||||
#define CC36 36 |
||||
#define CC37 37 |
||||
#define CC38 38 |
||||
#define CC39 39 |
||||
#define CC40 40 |
||||
#define CC41 41 |
||||
#define CC42 42 |
||||
#define CC43 43 |
||||
#define CC44 44 |
||||
#define CC45 45 |
||||
#define CC46 46 |
||||
#define CC47 47 |
||||
#define CC48 48 |
||||
#define CC49 49 |
||||
#define CC50 50 |
||||
#define CC51 51 |
||||
#define CC52 52 |
||||
#define CC53 53 |
||||
#define CC54 54 |
||||
#define CC55 55 |
||||
#define CC56 56 |
||||
#define CC57 57 |
||||
#define CC58 58 |
||||
#define CC59 59 |
||||
#define CC60 60 |
||||
#define CC61 61 |
||||
#define CC62 62 |
||||
#define CC63 63 |
||||
#define CC64 64 |
||||
#define CC65 65 |
||||
#define CC66 66 |
||||
#define CC67 67 |
||||
#define CC68 68 |
||||
#define CC69 69 |
||||
#define CC70 70 |
||||
#define CC71 71 |
||||
#define CC72 72 |
||||
#define CC73 73 |
||||
#define CC74 74 |
||||
#define CC75 75 |
||||
#define CC76 76 |
||||
#define CC77 77 |
||||
#define CC78 78 |
||||
#define CC79 79 |
||||
#define CC80 80 |
||||
#define CC81 81 |
||||
#define CC82 82 |
||||
#define CC83 83 |
||||
#define CC84 84 |
||||
#define CC85 85 |
||||
#define CC86 86 |
||||
#define CC87 87 |
||||
#define CC88 88 |
||||
#define CC89 89 |
||||
#define CC90 90 |
||||
#define CC91 91 |
||||
#define CC92 92 |
||||
#define CC93 93 |
||||
#define CC94 94 |
||||
#define CC95 95 |
||||
#define CC96 96 |
||||
#define CC97 97 |
||||
#define CC98 98 |
||||
#define CC99 99 |
||||
#define CC100 100 |
||||
#define CC101 101 |
||||
#define CC102 102 |
||||
#define CC103 103 |
||||
#define CC104 104 |
||||
#define CC105 105 |
||||
#define CC106 106 |
||||
#define CC107 107 |
||||
#define CC108 108 |
||||
#define CC109 109 |
||||
#define CC110 110 |
||||
#define CC111 111 |
||||
#define CC112 112 |
||||
#define CC113 113 |
||||
#define CC114 114 |
||||
#define CC115 115 |
||||
#define CC116 116 |
||||
#define CC117 117 |
||||
#define CC118 118 |
||||
#define CC119 119 |
||||
#define CC120 120 |
||||
#define CC121 121 |
||||
#define CC122 122 |
||||
#define CC123 123 |
||||
#define CC124 124 |
||||
#define CC125 125 |
||||
#define CC126 126 |
||||
#define CC127 127 |
||||
|
||||
// #define CC_BANK_SELECT CC0
|
||||
#define CC_MOD_WHEEL CC1 |
||||
// #define CC_BREATH_CTRL CC2
|
||||
#define CC_MODULATION_MIX CC3 |
||||
// #define CC_FOOT_CTRL CC4
|
||||
#define CC_PORTAMENTO_TIME CC5 |
||||
// #define CC_DATA_ENTRY_MSB CC6
|
||||
// #define CC_CHANNEL_VOL CC7
|
||||
// #define CC_BALANCE CC8
|
||||
#define CC_OSC_TUNE CC9 |
||||
// #define CC_PAN CC10
|
||||
// #define CC_EXPRESSION_CTRL CC11
|
||||
#define CC_OSC2_TUNE CC12 |
||||
#define CC_OSC3_TUNE CC13 |
||||
#define CC_OSC1_MIX CC14 |
||||
#define CC_OSC2_MIX CC15 |
||||
#define CC_OSC3_MIX CC16 |
||||
#define CC_NOISE_MIX CC17 |
||||
#define CC_FEEDBACK_MIX CC18 |
||||
#define CC_FILTER_BAND CC19 |
||||
#define CC_FILTER_CUTOFF_FREQ CC20 |
||||
#define CC_FILTER_EMPHASIS CC21 |
||||
#define CC_FILTER_CONTOUR CC22 |
||||
#define CC_FILTER_ATTACK CC23 |
||||
#define CC_FILTER_DECAY CC24 |
||||
#define CC_FILTER_SUSTAIN CC25 |
||||
#define CC_FILTER_RELEASE CC26 |
||||
#define CC_EG_ATTACK CC27 |
||||
#define CC_EG_DECAY CC28 |
||||
#define CC_EG_SUSTAIN CC29 |
||||
#define CC_EG_RELEASE CC30 |
||||
#define CC_LFO_RATE CC31 |
||||
// #define CC_BANK_SELECT_LSB CC32
|
||||
#define CC_MOD_WHEEL_LSB CC33 |
||||
// #define CC_BREATH_CTRL_LSB CC34
|
||||
#define CC_MODULATION_MIX_LSB CC35 |
||||
// #define CC_FOOT_CTRL_LSB CC36
|
||||
#define CC_PORTAMENTO_TIME_LSB CC37 |
||||
// #define CC_DATA_ENTRY_MSB_LSB CC38
|
||||
// #define CC_CHANNEL_VOL_LSB CC39
|
||||
// #define CC_BALANCE_LSB CC40
|
||||
#define CC_OSC_TUNE_LSB CC41 |
||||
// #define CC_PAN_LSB CC42
|
||||
// #define CC_EXPRESSION_CTRL_LSB CC43
|
||||
#define CC_OSC2_TUNE_LSB CC44 |
||||
#define CC_OSC3_TUNE_LSB CC45 |
||||
#define CC_OSC1_MIX_LSB CC46 |
||||
#define CC_OSC2_MIX_LSB CC47 |
||||
#define CC_OSC3_MIX_LSB CC48 |
||||
#define CC_NOISE_MIX_LSB CC49 |
||||
#define CC_FEEDBACK_MIX_LSB CC50 |
||||
#define CC_FILTER_BAND_LSB CC51 |
||||
#define CC_FILTER_CUTOFF_FREQ_LSB CC52 |
||||
#define CC_FILTER_EMPHASIS_LSB CC53 |
||||
#define CC_FILTER_CONTOUR_LSB CC54 |
||||
#define CC_FILTER_ATTACK_LSB CC55 |
||||
#define CC_FILTER_DECAY_LSB CC56 |
||||
#define CC_FILTER_SUSTAIN_LSB CC57 |
||||
#define CC_FILTER_RELEASE_LSB CC58 |
||||
#define CC_EG_ATTACK_LSB CC59 |
||||
#define CC_EG_DECAY_LSB CC60 |
||||
#define CC_EG_SUSTAIN_LSB CC61 |
||||
#define CC_EG_RELEASE_LSB CC62 |
||||
#define CC_LFO_RATE_LSB CC63 |
||||
// #define CC_DAMPER_PEDAL_ON_OFF CC64
|
||||
#define CC_PORTAMENTO_ON_OFF CC65 |
||||
// #define CC_SOSTENUTO_ON_OFF CC66
|
||||
// #define CC_SOFT_PEDAL_ON_OFF CC67
|
||||
// #define CC_LEGATO_PEDAL CC68
|
||||
// #define CC_HOLD_2 CC69
|
||||
// #define CC_SOUND_CTRL_1 CC70
|
||||
// #define CC_SOUND_CTRL_2 CC71
|
||||
// #define CC_SOUND_CTRL_3 CC72
|
||||
// #define CC_SOUND_CTRL_4 CC73
|
||||
// #define CC_SOUND_CTRL_5 CC74
|
||||
// #define CC_SOUND_CTRL_6 CC75
|
||||
// #define CC_SOUND_CTRL_7 CC76
|
||||
// #define CC_SOUND_CTRL_8 CC77
|
||||
// #define CC_SOUND_CTRL_9 CC78
|
||||
// #define CC_SOUND_CTRL_10 CC79
|
||||
// #define CC_GEN_PURPOSE_CTRL_5 CC80
|
||||
// #define CC_GEN_PURPOSE_CTRL_6 CC81
|
||||
// #define CC_GEN_PURPOSE_CTRL_7 CC82
|
||||
// #define CC_GEN_PURPOSE_CTRL_8 CC83
|
||||
// #define CC_PORTAMENTO_CTRL CC84
|
||||
// #define CC_ CC85
|
||||
// #define CC_ CC86
|
||||
// #define CC_ CC87
|
||||
// #define CC_ CC88
|
||||
// #define CC_ CC89
|
||||
#define CC_ASK_FOR_DATA CC90 |
||||
#define CC_BITCRUSH_OUT CC91 |
||||
// #define CC_EFFECT_2_DEPTH CC92
|
||||
// #define CC_EFFECT_3_DEPTH CC93
|
||||
// #define CC_EFFECT_4_DEPTH CC94
|
||||
// #define CC_EFFECT_5_DEPTH CC95
|
||||
// #define CC_DATA_INC CC96
|
||||
// #define CC_DATA_DEC CC97
|
||||
// #define CC_NRPN_LSB CC98
|
||||
// #define CC_NRPN_MSB CC99
|
||||
// #define CC_RPN_LSB CC100
|
||||
// #define CC_RPN_MSB CC101
|
||||
#define CC_OSC1_RANGE CC102 |
||||
#define CC_OSC1_WAVEFORM CC103 |
||||
#define CC_OSC2_RANGE CC104 |
||||
#define CC_OSC2_WAVEFORM CC105 |
||||
#define CC_OSC3_RANGE CC106 |
||||
#define CC_OSC3_WAVEFORM CC107 |
||||
#define CC_OSC3_CTRL CC108 |
||||
#define CC_FILTER_MOD CC109 |
||||
#define CC_FILTER_KEYTRACK_1 CC110 |
||||
#define CC_FILTER_KEYTRACK_2 CC111 |
||||
#define CC_TRANSPOSE CC112 |
||||
#define CC_FUNCTION CC113 |
||||
#define CC_NOISE_COLOR CC114 |
||||
#define CC_OSC_MOD CC115 |
||||
#define CC_DECAY_SW CC116 |
||||
#define CC_MOD_MIX_1 CC117 |
||||
#define CC_MOD_MIX_2 CC118 |
||||
#define CC_LFO_SHAPE CC119 |
||||
// #define CC_ALL_SOUND_OFF CC120
|
||||
// #define CC_RST_ALL_CTRL CC121
|
||||
// #define CC_LOCAL_CTRL_ON_OFF CC122
|
||||
// #define CC_ALL_NOTE_OFF CC123
|
||||
// #define CC_OMNI_MODE_OFF CC124
|
||||
// #define CC_OMNI_MODE_ON CC125
|
||||
// #define CC_MONO_MODE_ON CC126
|
||||
// #define CC_POLY_MODE_ON CC127
|
||||
|
||||
|
@ -0,0 +1,266 @@ |
||||
// Minimoog - mega 1
|
||||
/*
|
||||
* This program is part of a minimoog-like synthesizer based on teensy 4.0 |
||||
* Copyright (C) 2020 Pierre-Loup Martin |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/* This program is a synthesizer very similar to the minimoog model D.
|
||||
* It is intended to run on a Teensy 4.0, using the PJRC audio library. |
||||
* It also uses two Arduino Mega boards to manage all the user inputs : |
||||
* keyboard, switches, potentiometers, etc. |
||||
* All user inputs are handled and send to the teensy board using midi commands |
||||
*/ |
||||
|
||||
/*
|
||||
* This program is for the Arduino Mega 1, it handles the readings of : |
||||
* Category input type pin MIDI |
||||
*
|
||||
* Keyboard |
||||
* Keys switch 22-51 note on / note off |
||||
* Modulation |
||||
* LFO rate pot A0 CC 30 |
||||
* modulation mix pot A1 CC 3 |
||||
* glide pot A2 CC 5 |
||||
* pitchbend wheel pot A3 pitchbend change |
||||
* modulation wheel pot A4 CC 1 |
||||
* modulation mix 1 switch 2 CC 117 |
||||
* modulation mix 2 switch 3 CC 118 |
||||
* osc modulation switch 4 CC 115 |
||||
* glide switch 5 CC 65 |
||||
* LFO waveform switch 6 CC 119 |
||||
* Oscillators |
||||
* osc 1 range switch A5 CC 102 |
||||
* osc 1 waveform switch A6 CC 103 |
||||
* osc 2 range switch A7 CC 104 |
||||
* osc 2 waveform switch A8 CC 105 |
||||
* osc 3 range switch A9 CC 106 |
||||
* osc 3 waveform switch A10 CC 107 |
||||
* osc 3 control switch 7 CC 108 |
||||
* Mixer |
||||
* osc 1 mix pot A11 CC 85 |
||||
* osc 2 mix pot A12 CC 86 |
||||
* osc 3 mix pot A13 CC 87 |
||||
* noise mix pot A14 CC 88 |
||||
* external mix pot A15 CC 89 |
||||
* osc 1 switch 8 Directly added to mix |
||||
* osc 2 switch 9 ditto |
||||
* osc 3 switch 10 ditto |
||||
* noise switch 11 ditto |
||||
* external switch 12 ditto |
||||
* noise color switch 13 CC 114 |
||||
* Other |
||||
* function switch 14 CC 113 |
||||
* transpose + switch 52 CC 112 |
||||
* transpose - switch 53 CC 112 |
||||
* Communication |
||||
* TX1 to mega 2 18 |
||||
* RX1 from mega 2 19 |
||||
*/ |
||||
|
||||
// includes
|
||||
#include "MIDI.h" |
||||
#include "PushButton.h" |
||||
|
||||
// Constants
|
||||
const uint8_t NUM_KEYS = 30; |
||||
const uint8_t MIDI_OFFSET = 23; // to be modified
|
||||
// Digital pin definition
|
||||
|
||||
const uint8_t KEYS[NUM_KEYS] = { |
||||
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, |
||||
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, |
||||
46, 47, 48, 49, 50, 51 |
||||
}; |
||||
|
||||
PushButton keys[NUM_KEYS]; |
||||
|
||||
const uint8_t PIN_MOD_MIX_1 = 2; |
||||
const uint8_t PIN_MOD_MIX_2 = 3; |
||||
const uint8_t PIN_OSC_MOD = 4; |
||||
const uint8_t PIN_GLIDE = 5; |
||||
const uint8_t PIN_DECAY = 6; |
||||
const uint8_t PIN_LFO_WAVEFORM = 7; |
||||
|
||||
const uint8_t PIN_MIX_OSC_1 = 9; |
||||
const uint8_t PIN_MIX_OSC_2 = 10; |
||||
const uint8_t PIN_MIX_OSC_3 = 11; |
||||
const uint8_t PIN_MIX_OSC_NOISE = 12; |
||||
const uint8_t PIN_MIX_OSC_EXT = 13; |
||||
const uint8_t PIN_MIX_OSC_NOISE_COLOR = 14; |
||||
|
||||
const uint8_t PIN_TRANSPOSE_PLUS = 52; |
||||
const uint8_t PIN_TRANSPOSE_MINUS = 53; |
||||
|
||||
// Analog pin definition
|
||||
const uint8_t APIN_LFO_RATE = A0; |
||||
const uint8_t APIN_MOD_MIX = A1; |
||||
const uint8_t APIN_GLIDE = A2; |
||||
const uint8_t APIN_PITCH_WHEEL = A3; |
||||
const uint8_t APIN_MOD_WHEEL = A4; |
||||
|
||||
const uint8_t APIN_OSC_1_RANGE = A5; |
||||
const uint8_t APIN_OSC_1_WAVEFORM = A6; |
||||
const uint8_t APIN_OSC_2_RANGE = A7; |
||||
const uint8_t APIN_OSC_2_WAVEFORM = A8; |
||||
const uint8_t APIN_OSC_3_RANGE = A9; |
||||
const uint8_t APIN_OSC_3_WAVEFORM = A10; |
||||
|
||||
const uint8_t APIN_MIX_OSC_1 = A11; |
||||
const uint8_t APIN_MIX_OSC_2 = A12; |
||||
const uint8_t APIN_MIX_OSC_3 = A13; |
||||
const uint8_t APIN_MIX_NOISE = A14; |
||||
const uint8_t APIN_MIX_EXT = A15; |
||||
|
||||
|
||||
// Vars
|
||||
// Keyboard
|
||||
bool keyState[NUM_KEYS] = {}; |
||||
|
||||
// Modulation
|
||||
uint16_t lfoRate = 0; |
||||
uint16_t modMix = 0; |
||||
uint16_t glide = 0; |
||||
uint16_t pitchWheel = 0; |
||||
uint16_t modWheel = 0; |
||||
bool modMix1 = 0; |
||||
bool modMix2 = 0; |
||||
bool oscMod = 0; |
||||
bool glideEn = 0; |
||||
bool decayEn = 0; |
||||
bool lfoWaveform = 0; |
||||
|
||||
// Oscillators
|
||||
uint8_t osc1Range = 0; |
||||
uint8_t osc1Waveform = 0; |
||||
uint8_t osc2Range = 0; |
||||
uint8_t osc2Waveform = 0; |
||||
uint8_t osc3Range = 0; |
||||
uint8_t osc3Waveform = 0; |
||||
bool osc3Control = 0; |
||||
|
||||
// Mixer
|
||||
uint16_t osc1Mix = 0; |
||||
uint16_t osc2Mix = 0; |
||||
uint16_t osc3Mix = 0; |
||||
uint16_t feedbackMix = 0; |
||||
uint16_t noiseMix = 0; |
||||
bool osc1MixSw = 0; |
||||
bool osc2MixSw = 0; |
||||
bool osc3MixSw = 0; |
||||
bool feedbackMixSw = 0; |
||||
bool noiseMixSw = 0; |
||||
|
||||
// Miscellaneous
|
||||
bool function = 0; |
||||
|
||||
uint8_t defaultVelocity = 96; |
||||
|
||||
bool update = 0; |
||||
|
||||
struct midiSettings : public midi::DefaultSettings{ |
||||
// static const bool UseRunningStatus = true;
|
||||
static const long BaudRate = 115200; |
||||
}; |
||||
|
||||
// The one we use on synth
|
||||
//MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial1, midi1, midiSettings);
|
||||
// For debug purposes
|
||||
MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial, midi1, midiSettings); |
||||
|
||||
void setup(){ |
||||
// initialisation
|
||||
// Serial is for debug
|
||||
//Serial.begin(115200);
|
||||
|
||||
midi1.setHandleControlChange(handleControlChange); |
||||
midi1.begin(1); |
||||
// Serial 1 is for sending and receiving messages to and from Teensy
|
||||
// Serial1.begin(115200);
|
||||
// Serial 2 is for sending and receiving messages to and from Mega 2
|
||||
// Serial2.begin(115200);
|
||||
// keys
|
||||
/*
|
||||
for(uint8_t i = 0; i < NUM_KEYS; ++i){ |
||||
keyState[i] = 0; |
||||
pinMode(KEYS[i], INPUT_PULLUP); |
||||
} |
||||
*/ |
||||
|
||||
for(uint8_t i = 0; i < NUM_KEYS; ++i){ |
||||
keys[i].begin(KEYS[i], INPUT_PULLUP); |
||||
keys[i].setDebounceDelay(1); |
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
|
||||
void loop(){ |
||||
midi1.read(); |
||||
updateKeys(); |
||||
updateControls(); |
||||
updateSwitches(); |
||||
update = 0; |
||||
} |
||||
|
||||
void updateKeys(){ |
||||
// reading keys
|
||||
for(uint8_t i = 0; i < NUM_KEYS; ++i){ |
||||
/*
|
||||
bool newState = digitalRead(KEYS[i]); |
||||
if(newState != keyState[i]){ |
||||
uint8_t key = i + MIDI_OFFSET; |
||||
keyState[i] = newState; |
||||
if(newState){ |
||||
// MIDI note on
|
||||
midi1.sendNoteOn(key, defaultVelocity, 1); |
||||
|
||||
} else { |
||||
// MIDI note off
|
||||
midi1.sendNoteOff(key, 0, 1); |
||||
} |
||||
} |
||||
*/ |
||||
keys[i].update(); |
||||
uint8_t key = i + MIDI_OFFSET; |
||||
if(keys[i].justPressed()){ |
||||
midi1.sendNoteOn(key, defaultVelocity, 1); |
||||
} else if(keys[i].justReleased()){ |
||||
midi1.sendNoteOff(key, 0, 1); |
||||
} else { |
||||
// do nothing
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
void updateControls(){ |
||||
|
||||
|
||||
} |
||||
|
||||
void updateSwitches(){ |
||||
|
||||
} |
||||
|
||||
void handleControlChange(uint8_t channel, uint8_t command, uint8_t value){ |
||||
switch(command){ |
||||
case CC_ASK_FOR_DATA: |
||||
update = 1; |
||||
break; |
||||
} |
||||
} |
@ -0,0 +1,285 @@ |
||||
// Minimoog
|
||||
/*
|
||||
* This program is part of a minimoog-like synthesizer based on teensy 4.0 |
||||
* Copyright (C) 2020 Pierre-Loup Martin |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/* This program is a synthesizer very similar to the minimoog model D.
|
||||
* It is intended to run on a Teensy 4.0, using the PJRC audio library. |
||||
* It also uses two Arduino Mega boards to manage all the user inputs : |
||||
* keyboard, switches, potentiometers, etc. |
||||
* All user inputs are handled and send to the teensy board using midi commands |
||||
*/ |
||||
|
||||
#define CC0 0 |
||||
#define CC1 1 |
||||
#define CC2 2 |
||||
#define CC3 3 |
||||
#define CC4 4 |
||||
#define CC5 5 |
||||
#define CC6 6 |
||||
#define CC7 7 |
||||
#define CC8 8 |
||||
#define CC9 9 |
||||
#define CC10 10 |
||||
#define CC11 11 |
||||
#define CC12 12 |
||||
#define CC13 13 |
||||
#define CC14 14 |
||||
#define CC15 15 |
||||
#define CC16 16 |
||||
#define CC17 17 |
||||
#define CC18 18 |
||||
#define CC19 19 |
||||
#define CC20 20 |
||||
#define CC21 21 |
||||
#define CC22 22 |
||||
#define CC23 23 |
||||
#define CC24 24 |
||||
#define CC25 25 |
||||
#define CC26 26 |
||||
#define CC27 27 |
||||
#define CC28 28 |
||||
#define CC29 29 |
||||
#define CC30 30 |
||||
#define CC31 31 |
||||
#define CC32 32 |
||||
#define CC33 33 |
||||
#define CC34 34 |
||||
#define CC35 35 |
||||
#define CC36 36 |
||||
#define CC37 37 |
||||
#define CC38 38 |
||||
#define CC39 39 |
||||
#define CC40 40 |
||||
#define CC41 41 |
||||
#define CC42 42 |
||||
#define CC43 43 |
||||
#define CC44 44 |
||||
#define CC45 45 |
||||
#define CC46 46 |
||||
#define CC47 47 |
||||
#define CC48 48 |
||||
#define CC49 49 |
||||
#define CC50 50 |
||||
#define CC51 51 |
||||
#define CC52 52 |
||||
#define CC53 53 |
||||
#define CC54 54 |
||||
#define CC55 55 |
||||
#define CC56 56 |
||||
#define CC57 57 |
||||
#define CC58 58 |
||||
#define CC59 59 |
||||
#define CC60 60 |
||||
#define CC61 61 |
||||
#define CC62 62 |
||||
#define CC63 63 |
||||
#define CC64 64 |
||||
#define CC65 65 |
||||
#define CC66 66 |
||||
#define CC67 67 |
||||
#define CC68 68 |
||||
#define CC69 69 |
||||
#define CC70 70 |
||||
#define CC71 71 |
||||
#define CC72 72 |
||||
#define CC73 73 |
||||
#define CC74 74 |
||||
#define CC75 75 |
||||
#define CC76 76 |
||||
#define CC77 77 |
||||
#define CC78 78 |
||||
#define CC79 79 |
||||
#define CC80 80 |
||||
#define CC81 81 |
||||
#define CC82 82 |
||||
#define CC83 83 |
||||
#define CC84 84 |
||||
#define CC85 85 |
||||
#define CC86 86 |
||||
#define CC87 87 |
||||
#define CC88 88 |
||||
#define CC89 89 |
||||
#define CC90 90 |
||||
#define CC91 91 |
||||
#define CC92 92 |
||||
#define CC93 93 |
||||
#define CC94 94 |
||||
#define CC95 95 |
||||
#define CC96 96 |
||||
#define CC97 97 |
||||
#define CC98 98 |
||||
#define CC99 99 |
||||
#define CC100 100 |
||||
#define CC101 101 |
||||
#define CC102 102 |
||||
#define CC103 103 |
||||
#define CC104 104 |
||||
#define CC105 105 |
||||
#define CC106 106 |
||||
#define CC107 107 |
||||
#define CC108 108 |
||||
#define CC109 109 |
||||
#define CC110 110 |
||||
#define CC111 111 |
||||
#define CC112 112 |
||||
#define CC113 113 |
||||
#define CC114 114 |
||||
#define CC115 115 |
||||
#define CC116 116 |
||||
#define CC117 117 |
||||
#define CC118 118 |
||||
#define CC119 119 |
||||
#define CC120 120 |
||||
#define CC121 121 |
||||
#define CC122 122 |
||||
#define CC123 123 |
||||
#define CC124 124 |
||||
#define CC125 125 |
||||
#define CC126 126 |
||||
#define CC127 127 |
||||
|
||||
// #define CC_BANK_SELECT CC0
|
||||
#define CC_MOD_WHEEL CC1 |
||||
// #define CC_BREATH_CTRL CC2
|
||||
#define CC_MODULATION_MIX CC3 |
||||
// #define CC_FOOT_CTRL CC4
|
||||
#define CC_PORTAMENTO_TIME CC5 |
||||
// #define CC_DATA_ENTRY_MSB CC6
|
||||
// #define CC_CHANNEL_VOL CC7
|
||||
// #define CC_BALANCE CC8
|
||||
#define CC_OSC_TUNE CC9 |
||||
// #define CC_PAN CC10
|
||||
// #define CC_EXPRESSION_CTRL CC11
|
||||
#define CC_OSC2_TUNE CC12 |
||||
#define CC_OSC3_TUNE CC13 |
||||
#define CC_OSC1_MIX CC14 |
||||
#define CC_OSC2_MIX CC15 |
||||
#define CC_OSC3_MIX CC16 |
||||
#define CC_NOISE_MIX CC17 |
||||
#define CC_FEEDBACK_MIX CC18 |
||||
#define CC_FILTER_BAND CC19 |
||||
#define CC_FILTER_CUTOFF_FREQ CC20 |
||||
#define CC_FILTER_EMPHASIS CC21 |
||||
#define CC_FILTER_CONTOUR CC22 |
||||
#define CC_FILTER_ATTACK CC23 |
||||
#define CC_FILTER_DECAY CC24 |
||||
#define CC_FILTER_SUSTAIN CC25 |
||||
#define CC_FILTER_RELEASE CC26 |
||||
#define CC_EG_ATTACK CC27 |
||||
#define CC_EG_DECAY CC28 |
||||
#define CC_EG_SUSTAIN CC29 |
||||
#define CC_EG_RELEASE CC30 |
||||
#define CC_LFO_RATE CC31 |
||||
// #define CC_BANK_SELECT_LSB CC32
|
||||
#define CC_MOD_WHEEL_LSB CC33 |
||||
// #define CC_BREATH_CTRL_LSB CC34
|
||||
#define CC_MODULATION_MIX_LSB CC35 |
||||
// #define CC_FOOT_CTRL_LSB CC36
|
||||
#define CC_PORTAMENTO_TIME_LSB CC37 |
||||
// #define CC_DATA_ENTRY_MSB_LSB CC38
|
||||
// #define CC_CHANNEL_VOL_LSB CC39
|
||||
// #define CC_BALANCE_LSB CC40
|
||||
#define CC_OSC_TUNE_LSB CC41 |
||||
// #define CC_PAN_LSB CC42
|
||||
// #define CC_EXPRESSION_CTRL_LSB CC43
|
||||
#define CC_OSC2_TUNE_LSB CC44 |
||||
#define CC_OSC3_TUNE_LSB CC45 |
||||
#define CC_OSC1_MIX_LSB CC46 |
||||
#define CC_OSC2_MIX_LSB CC47 |
||||
#define CC_OSC3_MIX_LSB CC48 |
||||
#define CC_NOISE_MIX_LSB CC49 |
||||
#define CC_FEEDBACK_MIX_LSB CC50 |
||||
#define CC_FILTER_BAND_LSB CC51 |
||||
#define CC_FILTER_CUTOFF_FREQ_LSB CC52 |
||||
#define CC_FILTER_EMPHASIS_LSB CC53 |
||||
#define CC_FILTER_CONTOUR_LSB CC54 |
||||
#define CC_FILTER_ATTACK_LSB CC55 |
||||
#define CC_FILTER_DECAY_LSB CC56 |
||||
#define CC_FILTER_SUSTAIN_LSB CC57 |
||||
#define CC_FILTER_RELEASE_LSB CC58 |
||||
#define CC_EG_ATTACK_LSB CC59 |
||||
#define CC_EG_DECAY_LSB CC60 |
||||
#define CC_EG_SUSTAIN_LSB CC61 |
||||
#define CC_EG_RELEASE_LSB CC62 |
||||
#define CC_LFO_RATE_LSB CC63 |
||||
// #define CC_DAMPER_PEDAL_ON_OFF CC64
|
||||
#define CC_PORTAMENTO_ON_OFF CC65 |
||||
// #define CC_SOSTENUTO_ON_OFF CC66
|
||||
// #define CC_SOFT_PEDAL_ON_OFF CC67
|
||||
// #define CC_LEGATO_PEDAL CC68
|
||||
// #define CC_HOLD_2 CC69
|
||||
// #define CC_SOUND_CTRL_1 CC70
|
||||
// #define CC_SOUND_CTRL_2 CC71
|
||||
// #define CC_SOUND_CTRL_3 CC72
|
||||
// #define CC_SOUND_CTRL_4 CC73
|
||||
// #define CC_SOUND_CTRL_5 CC74
|
||||
// #define CC_SOUND_CTRL_6 CC75
|
||||
// #define CC_SOUND_CTRL_7 CC76
|
||||
// #define CC_SOUND_CTRL_8 CC77
|
||||
// #define CC_SOUND_CTRL_9 CC78
|
||||
// #define CC_SOUND_CTRL_10 CC79
|
||||
// #define CC_GEN_PURPOSE_CTRL_5 CC80
|
||||
// #define CC_GEN_PURPOSE_CTRL_6 CC81
|
||||
// #define CC_GEN_PURPOSE_CTRL_7 CC82
|
||||
// #define CC_GEN_PURPOSE_CTRL_8 CC83
|
||||
// #define CC_PORTAMENTO_CTRL CC84
|
||||
// #define CC_ CC85
|
||||
// #define CC_ CC86
|
||||
// #define CC_ CC87
|
||||
// #define CC_ CC88
|
||||
// #define CC_ CC89
|
||||
#define CC_ASK_FOR_DATA CC90 |
||||
#define CC_BITCRUSH_OUT CC91 |
||||
// #define CC_EFFECT_2_DEPTH CC92
|
||||
// #define CC_EFFECT_3_DEPTH CC93
|
||||
// #define CC_EFFECT_4_DEPTH CC94
|
||||
// #define CC_EFFECT_5_DEPTH CC95
|
||||
// #define CC_DATA_INC CC96
|
||||
// #define CC_DATA_DEC CC97
|
||||
// #define CC_NRPN_LSB CC98
|
||||
// #define CC_NRPN_MSB CC99
|
||||
// #define CC_RPN_LSB CC100
|
||||
// #define CC_RPN_MSB CC101
|
||||
#define CC_OSC1_RANGE CC102 |
||||
#define CC_OSC1_WAVEFORM CC103 |
||||
#define CC_OSC2_RANGE CC104 |
||||
#define CC_OSC2_WAVEFORM CC105 |
||||
#define CC_OSC3_RANGE CC106 |
||||
#define CC_OSC3_WAVEFORM CC107 |
||||
#define CC_OSC3_CTRL CC108 |
||||
#define CC_FILTER_MOD CC109 |
||||
#define CC_FILTER_KEYTRACK_1 CC110 |
||||
#define CC_FILTER_KEYTRACK_2 CC111 |
||||
#define CC_TRANSPOSE CC112 |
||||
#define CC_FUNCTION CC113 |
||||
#define CC_NOISE_COLOR CC114 |
||||
#define CC_OSC_MOD CC115 |
||||
#define CC_DECAY_SW CC116 |
||||
#define CC_MOD_MIX_1 CC117 |
||||
#define CC_MOD_MIX_2 CC118 |
||||
#define CC_LFO_SHAPE CC119 |
||||
// #define CC_ALL_SOUND_OFF CC120
|
||||
// #define CC_RST_ALL_CTRL CC121
|
||||
// #define CC_LOCAL_CTRL_ON_OFF CC122
|
||||
// #define CC_ALL_NOTE_OFF CC123
|
||||
// #define CC_OMNI_MODE_OFF CC124
|
||||
// #define CC_OMNI_MODE_ON CC125
|
||||
// #define CC_MONO_MODE_ON CC126
|
||||
// #define CC_POLY_MODE_ON CC127
|
||||
|
||||
|
@ -0,0 +1,253 @@ |
||||
// Minimoog - mega 2
|
||||
/*
|
||||
* This program is part of a minimoog-like synthesizer based on teensy 4.0 |
||||
* Copyright (C) 2020 Pierre-Loup Martin |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/* This program is a synthesizer very similar to the minimoog model D.
|
||||
* It is intended to run on a Teensy 4.0, using the PJRC audio library. |
||||
* It also uses two Arduino Mega boards to manage all the user inputs : |
||||
* keyboard, switches, potentiometers, etc. |
||||
* All user inputs are handled and send to the teensy board using midi commands |
||||
*/ |
||||
|
||||
/*
|
||||
* This program is for the Arduino Mega 2, it handles the readings of : |
||||
* Category input type pin MIDI |
||||
*
|
||||
* Oscillators |
||||
* global tune pot A0 CC 9 |
||||
* osc 2 tune pot A1 CC 14 |
||||
* osc 3 tune pot A2 CC 15 |
||||
* Filter |
||||
* filter pass pot A3 CC 19 |
||||
* cutoff frequency pot A4 CC 20 |
||||
* emphasis pot A5 CC 21 |
||||
* contour pot A6 CC 22 |
||||
* attack pot A7 CC 23 |
||||
* decay pot A8 CC 24 |
||||
* sustain pot A9 CC 25 |
||||
* release pot A10 CC 26 |
||||
* filter modulation switch 2 CC 109 |
||||
* keyboard control 1 switch 3 CC 110 |
||||
* keyboard control 2 switch 4 CC 111 |
||||
* Enveloppe |
||||
* attack pot A11 CC 27 |
||||
* decay pot A12 CC 28 |
||||
* sustain pot A13 CC 29 |
||||
* release pot A14 CC 30 |
||||
* Communication |
||||
* TX1 to teensy 18 |
||||
* RX1 from teensy 19 |
||||
* TX2 to mega 1 16 |
||||
* RX2 from mega 1 17 |
||||
*/ |
||||
|
||||
// includes
|
||||
#include "MIDI.h" |
||||
#include "PushButton.h" |
||||
#include "ExpFilter.h" |
||||
|
||||
#include "defs.h" |
||||
|
||||
// Constants
|
||||
const uint8_t NUM_SWITCHES = 3; |
||||
const uint8_t NUM_POTS = 15; |
||||
const uint8_t POT_FILTER_COEF = 10; |
||||
|
||||
// Digital pin definition
|
||||
const uint8_t PIN_FILTER_MOD = 2; |
||||
const uint8_t PIN_KEYBOARD_CTRL_1 = 3; |
||||
const uint8_t PIN_KEYBOARD_CTRL_2 = 4; |
||||
|
||||
// Analog pin definition
|
||||
const uint8_t APIN_GLOBAL_TUNE = A0; |
||||
const uint8_t APIN_OSC2_TUNE = A1; |
||||
const uint8_t APIN_OSC3_TUNE = A2; |
||||
const uint8_t APIN_FILTER_BAND = A3; |
||||
const uint8_t APIN_FILTER_CUTOFF = A4; |
||||
const uint8_t APIN_FILTER_EMPHASIS = A5; |
||||
const uint8_t APIN_FILTER_CONTOUR = A6; |
||||
const uint8_t APIN_FILTER_ATTACK = A7; |
||||
const uint8_t APIN_FILTER_DECAY = A8; |
||||
const uint8_t APIN_FILTER_SUSTAIN = A9; |
||||
const uint8_t APIN_FILTER_RELEASE = A10; |
||||
const uint8_t APIN_ATTACK = A11; |
||||
const uint8_t APIN_DECAY = A12; |
||||
const uint8_t APIN_SUSTAIN = A13; |
||||
const uint8_t APIN_RELEASE = A14; |
||||
|
||||
const uint8_t apin[NUM_POTS] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14}; |
||||
|
||||
// Variables
|
||||
uint16_t potState[NUM_POTS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
||||
|
||||
PushButton switches[NUM_SWITCHES]; |
||||
ExpFilter pots[NUM_POTS]; |
||||
|
||||
bool update = 0; |
||||
|
||||
struct midiSettings : public midi::DefaultSettings{ |
||||
// static const bool UseRunningStatus = true;
|
||||
static const long BaudRate = 115200; |
||||
}; |
||||
|
||||
// The one we use on synth
|
||||
MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial1, midi1, midiSettings); |
||||
// For debug purposes
|
||||
//MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial, midi1, midiSettings);
|
||||
|
||||
|
||||
void setup(){ |
||||
for(uint8_t i = 0; i < NUM_SWITCHES; ++i){ |
||||
switches[i].begin(i + PIN_FILTER_MOD, INPUT_PULLUP); |
||||
switches[i].setDebounceDelay(1); |
||||
} |
||||
|
||||
for (uint8_t i = 0; i < NUM_POTS; ++i){ |
||||
pots[i].begin(analogRead(apin[i])); |
||||
pots[i].setCoef(POT_FILTER_COEF); |
||||
} |
||||
|
||||
midi1.setHandleControlChange(handleControlChange); |
||||
midi1.begin(1); |
||||
midi1.turnThruOff(); |
||||
|
||||
} |
||||
|
||||
void loop(){ |
||||
midi1.read(); |
||||
updateControls(); |
||||
updateSwitches(); |
||||
update = 0; |
||||
} |
||||
|
||||
void updateControls(){ |
||||
for(uint8_t i = 0; i < NUM_POTS; ++i){ |
||||
uint16_t value = 0; |
||||
|
||||
value = pots[i].filter(analogRead(apin[i])); |
||||
if((value != potState[i]) || update){ |
||||
potState[i] = value; |
||||
} else { |
||||
// If not change, skip midi update
|
||||
continue;
|
||||
} |
||||
|
||||
uint8_t controlChange = 0; |
||||
|
||||
switch(i){ |
||||
case 0: |
||||
controlChange = CC_OSC_TUNE; |
||||
break; |
||||
case 1: |
||||
controlChange = CC_OSC2_TUNE; |
||||
break; |
||||
case 2: |
||||
controlChange = CC_OSC3_TUNE; |
||||
break; |
||||
case 3: |
||||
controlChange = CC_FILTER_BAND; |
||||
break; |
||||
case 4: |
||||
controlChange = CC_FILTER_CUTOFF_FREQ; |
||||
break; |
||||
case 5: |
||||
controlChange = CC_FILTER_EMPHASIS; |
||||
break; |
||||
case 6: |
||||
controlChange = CC_FILTER_CONTOUR; |
||||
break; |
||||
case 7: |
||||
controlChange = CC_FILTER_ATTACK; |
||||
break; |
||||
case 8: |
||||
controlChange = CC_FILTER_DECAY; |
||||
break; |
||||
case 9: |
||||
controlChange = CC_FILTER_SUSTAIN; |
||||
break; |
||||
case 10: |
||||
controlChange = CC_FILTER_RELEASE; |
||||
break; |
||||
case 11: |
||||
controlChange = CC_EG_ATTACK; |
||||
break; |
||||
case 12: |
||||
controlChange = CC_EG_DECAY; |
||||
break; |
||||
case 13: |
||||
controlChange = CC_EG_SUSTAIN; |
||||
break; |
||||
case 14: |
||||
controlChange = CC_EG_RELEASE; |
||||
break; |
||||
default: |
||||
continue; |
||||
|
||||
} |
||||
uint8_t valueHigh = value >> 7; |
||||
uint8_t valueLow = value & 0x7F; |
||||
midi1.sendControlChange(controlChange, valueHigh, 1); |
||||
midi1.sendControlChange(controlChange + 32, valueLow, 1); |
||||
} |
||||
} |
||||
|
||||
void updateSwitches(){ |
||||
for(uint8_t i = 0; i < NUM_SWITCHES; ++i){ |
||||
uint8_t change = 0; |
||||
switches[i].update(); |
||||
|
||||
if(switches[i].justPressed()){ |
||||
change = 127; |
||||
} else if(switches[i].justReleased()){ |
||||
change = 0; |
||||
} else if(update){ |
||||
change = (uint8_t)switches[i].isPressed(); |
||||
change *= 127; |
||||
} else { |
||||
// If no change, skip the midi command sending.
|
||||
continue; |
||||
} |
||||
|
||||
uint8_t controlChange = 0; |
||||
|
||||
switch(i){ |
||||
case 0: |
||||
controlChange = CC_FILTER_MOD; |
||||
break; |
||||
case 1: |
||||
controlChange = CC_FILTER_KEYTRACK_1; |
||||
break; |
||||
case 2: |
||||
controlChange = CC_FILTER_KEYTRACK_2; |
||||
break; |
||||
default: |
||||
continue;
|
||||
} |
||||
|
||||
midi1.sendControlChange(controlChange, change, 1); |
||||
} |
||||
} |
||||
|
||||
|
||||
void handleControlChange(uint8_t channel, uint8_t command, uint8_t value){ |
||||
switch(command){ |
||||
case CC_ASK_FOR_DATA: |
||||
update = 1; |
||||
break; |
||||
} |
||||
} |
@ -0,0 +1,96 @@ |
||||
#include <Audio.h> |
||||
#include <Wire.h> |
||||
#include <SPI.h> |
||||
#include <SD.h> |
||||
#include <SerialFlash.h> |
||||
|
||||
// GUItool: begin automatically generated code
|
||||
AudioSynthWaveformDc dcFilterEnvelope; //xy=169.76666259765625,540.0000305175781
|
||||
AudioSynthWaveformDc dcOscTune; //xy=228.76666259765625,149
|
||||
AudioSynthWaveformDc dcKeyTrack; //xy=231.76666259765625,113
|
||||
AudioSynthWaveformDc dcPitchBend; //xy=234.7666778564453,184.00001525878906
|
||||
AudioSynthWaveformDc dcFilter; //xy=336.76666259765625,595.0000305175781
|
||||
AudioSynthNoisePink pinkNoise; //xy=358.76666259765625,320
|
||||
AudioSynthNoiseWhite whiteNoise; //xy=361.76666259765625,284
|
||||
AudioSynthWaveformDc dcLfoFreq; //xy=365.76666259765625,376
|
||||
AudioEffectEnvelope filterEnvelope; //xy=367.76666259765625,540.0000305175781
|
||||
AudioSynthWaveformDc dcFilterKeyTrack; //xy=369.76666259765625,629.0000305175781
|
||||
AudioAmplifier ampPitchBend; //xy=407.7666778564453,184.00001525878906
|
||||
AudioMixer4 noiseMixer; //xy=544.7666625976562,317
|
||||
AudioSynthWaveformModulated lfoWaveform; //xy=548.7666625976562,374
|
||||
AudioAmplifier ampOsc3Mod; //xy=549.7666625976562,437
|
||||
AudioAmplifier ampModEg; //xy=559.7666625976562,475
|
||||
AudioMixer4 mainTuneMixer; //xy=631.7666625976562,133
|
||||
AudioMixer4 modMix2; //xy=755.7666015625,470
|
||||
AudioMixer4 modMix1; //xy=756.7666015625,399
|
||||
AudioSynthWaveformDc dcOsc3; //xy=758.7667541503906,193.00001525878906
|
||||
AudioMixer4 osc3ControlMixer; //xy=933.7667236328125,199
|
||||
AudioMixer4 modMixer; //xy=945.7666015625,448
|
||||
AudioSynthWaveformDc dcOsc2Tune; //xy=1105.566650390625,155.56666564941406
|
||||
AudioSynthWaveformDc dcOsc3Tune; //xy=1106.36669921875,221.56666564941406
|
||||
AudioAmplifier ampModWheel; //xy=1159.7666015625,448
|
||||
AudioMixer4 osc3TuneMixer; //xy=1289.36669921875,217.56666564941406
|
||||
AudioMixer4 osc2TuneMixer; //xy=1290.566650390625,153.56666564941406
|
||||
AudioSynthWaveformDc dcPulse; //xy=1306.566665649414,65.56666564941406
|
||||
AudioSynthWaveformModulated osc1Waveform; //xy=1523.7666015625,114
|
||||
AudioSynthWaveformModulated osc2Waveform; //xy=1524.7666015625,151
|
||||
AudioSynthWaveformModulated osc3Waveform; //xy=1524.7666015625,188
|
||||
AudioMixer4 oscMixer; //xy=1710.7666015625,157
|
||||
AudioMixer4 globalMixer; //xy=1919.7666015625,204
|
||||
AudioAmplifier ampPreFilter; //xy=2083.7666015625,203
|
||||
AudioMixer4 filterMixer; //xy=2101.7666625976562,446
|
||||
AudioFilterStateVariable vcf; //xy=2270.7666625976562,440
|
||||
AudioMixer4 bandMixer; //xy=2441.566665649414,435.56666564941406
|
||||
AudioEffectEnvelope mainEnvelope; //xy=2620.7664794921875,436
|
||||
AudioEffectBitcrusher bitCrushOutput; //xy=2856.5662841796875,433.566650390625
|
||||
AudioOutputI2S i2s; //xy=3046.7659912109375,435
|
||||
AudioConnection patchCord1(dcFilterEnvelope, filterEnvelope); |
||||
AudioConnection patchCord2(dcOscTune, 0, mainTuneMixer, 1); |
||||
AudioConnection patchCord3(dcKeyTrack, 0, mainTuneMixer, 0); |
||||
AudioConnection patchCord4(dcPitchBend, ampPitchBend); |
||||
AudioConnection patchCord5(dcFilter, 0, filterMixer, 2); |
||||
AudioConnection patchCord6(pinkNoise, 0, noiseMixer, 1); |
||||
AudioConnection patchCord7(whiteNoise, 0, noiseMixer, 0); |
||||
AudioConnection patchCord8(dcLfoFreq, 0, lfoWaveform, 0); |
||||
AudioConnection patchCord9(filterEnvelope, 0, filterMixer, 1); |
||||
AudioConnection patchCord10(filterEnvelope, ampModEg); |
||||
AudioConnection patchCord11(dcFilterKeyTrack, 0, filterMixer, 3); |
||||
AudioConnection patchCord12(ampPitchBend, 0, mainTuneMixer, 2); |
||||
AudioConnection patchCord13(noiseMixer, 0, modMix1, 0); |
||||
AudioConnection patchCord14(noiseMixer, 0, oscMixer, 3); |
||||
AudioConnection patchCord15(lfoWaveform, 0, modMix1, 1); |
||||
AudioConnection patchCord16(ampOsc3Mod, 0, modMix2, 0); |
||||
AudioConnection patchCord17(ampModEg, 0, modMix2, 1); |
||||
AudioConnection patchCord18(mainTuneMixer, 0, osc3ControlMixer, 0); |
||||
AudioConnection patchCord19(mainTuneMixer, 0, osc1Waveform, 0); |
||||
AudioConnection patchCord20(mainTuneMixer, 0, osc2TuneMixer, 0); |
||||
AudioConnection patchCord21(modMix2, 0, modMixer, 1); |
||||
AudioConnection patchCord22(modMix1, 0, modMixer, 0); |
||||
AudioConnection patchCord23(dcOsc3, 0, osc3ControlMixer, 1); |
||||
AudioConnection patchCord24(osc3ControlMixer, 0, osc3TuneMixer, 0); |
||||
AudioConnection patchCord25(modMixer, ampModWheel); |
||||
AudioConnection patchCord26(dcOsc2Tune, 0, osc2TuneMixer, 1); |
||||
AudioConnection patchCord27(dcOsc3Tune, 0, osc3TuneMixer, 1); |
||||
AudioConnection patchCord28(ampModWheel, 0, filterMixer, 0); |
||||
AudioConnection patchCord29(ampModWheel, 0, mainTuneMixer, 3); |
||||
AudioConnection patchCord30(osc3TuneMixer, 0, osc3Waveform, 0); |
||||
AudioConnection patchCord31(osc2TuneMixer, 0, osc2Waveform, 0); |
||||
AudioConnection patchCord32(dcPulse, 0, osc1Waveform, 1); |
||||
AudioConnection patchCord33(dcPulse, 0, osc2Waveform, 1); |
||||
AudioConnection patchCord34(dcPulse, 0, osc3Waveform, 1); |
||||
AudioConnection patchCord35(osc1Waveform, 0, oscMixer, 0); |
||||
AudioConnection patchCord36(osc2Waveform, 0, oscMixer, 1); |
||||
AudioConnection patchCord37(osc3Waveform, 0, oscMixer, 2); |
||||
AudioConnection patchCord38(osc3Waveform, ampOsc3Mod); |
||||
AudioConnection patchCord39(oscMixer, 0, globalMixer, 0); |
||||
AudioConnection patchCord40(globalMixer, ampPreFilter); |
||||
AudioConnection patchCord41(ampPreFilter, 0, vcf, 0); |
||||
AudioConnection patchCord42(filterMixer, 0, vcf, 1); |
||||
AudioConnection patchCord43(vcf, 0, bandMixer, 0); |
||||
AudioConnection patchCord44(vcf, 2, bandMixer, 1); |
||||
AudioConnection patchCord45(bandMixer, mainEnvelope); |
||||
AudioConnection patchCord46(mainEnvelope, 0, globalMixer, 1); |
||||
AudioConnection patchCord47(mainEnvelope, bitCrushOutput); |
||||
AudioConnection patchCord48(bitCrushOutput, 0, i2s, 0); |
||||
AudioConnection patchCord49(bitCrushOutput, 0, i2s, 1); |
||||
// GUItool: end automatically generated code
|
@ -0,0 +1,283 @@ |
||||
// Minimoog
|
||||
/*
|
||||
* This program is part of a minimoog-like synthesizer based on teensy 4.0 |
||||
* Copyright (C) 2020 Pierre-Loup Martin |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/* This program is a synthesizer very similar to the minimoog model D.
|
||||
* It is intended to run on a Teensy 4.0, using the PJRC audio library. |
||||
* It also uses two Arduino Mega boards to manage all the user inputs : |
||||
* keyboard, switches, potentiometers, etc. |
||||
* All user inputs are handled and send to the teensy board using midi commands |
||||
*/ |
||||
|
||||
#define CC0 0 |
||||
#define CC1 1 |
||||
#define CC2 2 |
||||
#define CC3 3 |
||||
#define CC4 4 |
||||
#define CC5 5 |
||||
#define CC6 6 |
||||
#define CC7 7 |
||||
#define CC8 8 |
||||
#define CC9 9 |
||||
#define CC10 10 |
||||
#define CC11 11 |
||||
#define CC12 12 |
||||
#define CC13 13 |
||||
#define CC14 14 |
||||
#define CC15 15 |
||||
#define CC16 16 |
||||
#define CC17 17 |
||||
#define CC18 18 |
||||
#define CC19 19 |
||||
#define CC20 20 |
||||
#define CC21 21 |
||||
#define CC22 22 |
||||
#define CC23 23 |
||||
#define CC24 24 |
||||
#define CC25 25 |
||||
#define CC26 26 |
||||
#define CC27 27 |
||||
#define CC28 28 |
||||
#define CC29 29 |
||||
#define CC30 30 |
||||
#define CC31 31 |
||||
#define CC32 32 |
||||
#define CC33 33 |
||||
#define CC34 34 |
||||
#define CC35 35 |
||||
#define CC36 36 |
||||
#define CC37 37 |
||||
#define CC38 38 |
||||
#define CC39 39 |
||||
#define CC40 40 |
||||
#define CC41 41 |
||||
#define CC42 42 |
||||
#define CC43 43 |
||||
#define CC44 44 |
||||
#define CC45 45 |
||||
#define CC46 46 |
||||
#define CC47 47 |
||||
#define CC48 48 |
||||
#define CC49 49 |
||||
#define CC50 50 |
||||
#define CC51 51 |
||||
#define CC52 52 |
||||
#define CC53 53 |
||||
#define CC54 54 |
||||
#define CC55 55 |
||||
#define CC56 56 |
||||
#define CC57 57 |
||||
#define CC58 58 |
||||
#define CC59 59 |
||||
#define CC60 60 |
||||
#define CC61 61 |
||||
#define CC62 62 |
||||
#define CC63 63 |
||||
#define CC64 64 |
||||
#define CC65 65 |
||||
#define CC66 66 |
||||
#define CC67 67 |
||||
#define CC68 68 |
||||
#define CC69 69 |
||||
#define CC70 70 |
||||
#define CC71 71 |
||||
#define CC72 72 |
||||
#define CC73 73 |
||||
#define CC74 74 |
||||
#define CC75 75 |
||||
#define CC76 76 |
||||
#define CC77 77 |
||||
#define CC78 78 |
||||
#define CC79 79 |
||||
#define CC80 80 |
||||
#define CC81 81 |
||||
#define CC82 82 |
||||
#define CC83 83 |
||||
#define CC84 84 |
||||
#define CC85 85 |
||||
#define CC86 86 |
||||
#define CC87 87 |
||||
#define CC88 88 |
||||
#define CC89 89 |
||||
#define CC90 90 |
||||
#define CC91 91 |
||||
#define CC92 92 |
||||
#define CC93 93 |
||||
#define CC94 94 |
||||
#define CC95 95 |
||||
#define CC96 96 |
||||
#define CC97 97 |
||||
#define CC98 98 |
||||
#define CC99 99 |
||||
#define CC100 100 |
||||
#define CC101 101 |
||||
#define CC102 102 |
||||
#define CC103 103 |
||||
#define CC104 104 |
||||
#define CC105 105 |
||||
#define CC106 106 |
||||
#define CC107 107 |
||||
#define CC108 108 |
||||
#define CC109 109 |
||||
#define CC110 110 |
||||
#define CC111 111 |
||||
#define CC112 112 |
||||
#define CC113 113 |
||||
#define CC114 114 |
||||
#define CC115 115 |
||||
#define CC116 116 |
||||
#define CC117 117 |
||||
#define CC118 118 |
||||
#define CC119 119 |
||||
#define CC120 120 |
||||
#define CC121 121 |
||||
#define CC122 122 |
||||
#define CC123 123 |
||||
#define CC124 124 |
||||
#define CC125 125 |
||||
#define CC126 126 |
||||
#define CC127 127 |
||||
|
||||
// #define CC_BANK_SELECT CC0
|
||||
#define CC_MOD_WHEEL CC1 |
||||
// #define CC_BREATH_CTRL CC2
|
||||
#define CC_MODULATION_MIX CC3 |
||||
// #define CC_FOOT_CTRL CC4
|
||||
#define CC_PORTAMENTO_TIME CC5 |
||||
// #define CC_DATA_ENTRY_MSB CC6
|
||||
// #define CC_CHANNEL_VOL CC7
|
||||
// #define CC_BALANCE CC8
|
||||
#define CC_OSC_TUNE CC9 |
||||
// #define CC_PAN CC10
|
||||
// #define CC_EXPRESSION_CTRL CC11
|
||||
#define CC_OSC2_TUNE CC12 |
||||
#define CC_OSC3_TUNE CC13 |
||||
#define CC_OSC1_MIX CC14 |
||||
#define CC_OSC2_MIX CC15 |
||||
#define CC_OSC3_MIX CC16 |
||||
#define CC_NOISE_MIX CC17 |
||||
#define CC_FEEDBACK_MIX CC18 |
||||
#define CC_FILTER_BAND CC19 |
||||
#define CC_FILTER_CUTOFF_FREQ CC20 |
||||
#define CC_FILTER_EMPHASIS CC21 |
||||
#define CC_FILTER_CONTOUR CC22 |
||||
#define CC_FILTER_ATTACK CC23 |
||||
#define CC_FILTER_DECAY CC24 |
||||
#define CC_FILTER_SUSTAIN CC25 |
||||
#define CC_FILTER_RELEASE CC26 |
||||
#define CC_EG_ATTACK CC27 |
||||
#define CC_EG_DECAY CC28 |
||||
#define CC_EG_SUSTAIN CC29 |
||||
#define CC_EG_RELEASE CC30 |
||||
#define CC_LFO_RATE CC31 |
||||
// #define CC_BANK_SELECT_LSB CC32
|
||||
#define CC_MOD_WHEEL_LSB CC33 |
||||
// #define CC_BREATH_CTRL_LSB CC34
|
||||
#define CC_MODULATION_MIX_LSB CC35 |
||||
// #define CC_FOOT_CTRL_LSB CC36
|
||||
#define CC_PORTAMENTO_TIME_LSB CC37 |
||||
// #define CC_DATA_ENTRY_MSB_LSB CC38
|
||||
// #define CC_CHANNEL_VOL_LSB CC39
|
||||
// #define CC_BALANCE_LSB CC40
|
||||
#define CC_OSC_TUNE_LSB CC41 |
||||
// #define CC_PAN_LSB CC42
|
||||
// #define CC_EXPRESSION_CTRL_LSB CC43
|
||||
#define CC_OSC2_TUNE_LSB CC44 |
||||
#define CC_OSC3_TUNE_LSB CC45 |
||||
#define CC_OSC1_MIX_LSB CC46 |
||||
#define CC_OSC2_MIX_LSB CC47 |
||||
#define CC_OSC3_MIX_LSB CC48 |
||||
#define CC_NOISE_MIX_LSB CC49 |
||||
#define CC_FEEDBACK_MIX_LSB CC50 |
||||
#define CC_FILTER_BAND_LSB CC51 |
||||
#define CC_FILTER_CUTOFF_FREQ_LSB CC52 |
||||
#define CC_FILTER_EMPHASIS_LSB CC53 |
||||
#define CC_FILTER_CONTOUR_LSB CC54 |
||||
#define CC_FILTER_ATTACK_LSB CC55 |
||||
#define CC_FILTER_DECAY_LSB CC56 |
||||
#define CC_FILTER_SUSTAIN_LSB CC57 |
||||
#define CC_FILTER_RELEASE_LSB CC58 |
||||
#define CC_EG_ATTACK_LSB CC59 |
||||
#define CC_EG_DECAY_LSB CC60 |
||||
#define CC_EG_SUSTAIN_LSB CC61 |
||||
#define CC_EG_RELEASE_LSB CC62 |
||||
#define CC_LFO_RATE_LSB CC63 |
||||
// #define CC_DAMPER_PEDAL_ON_OFF CC64
|
||||
#define CC_PORTAMENTO_ON_OFF CC65 |
||||
// #define CC_SOSTENUTO_ON_OFF CC66
|
||||
// #define CC_SOFT_PEDAL_ON_OFF CC67
|
||||
// #define CC_LEGATO_PEDAL CC68
|
||||
// #define CC_HOLD_2 CC69
|
||||
// #define CC_SOUND_CTRL_1 CC70
|
||||
// #define CC_SOUND_CTRL_2 CC71
|
||||
// #define CC_SOUND_CTRL_3 CC72
|
||||
// #define CC_SOUND_CTRL_4 CC73
|
||||
// #define CC_SOUND_CTRL_5 CC74
|
||||
// #define CC_SOUND_CTRL_6 CC75
|
||||
// #define CC_SOUND_CTRL_7 CC76
|
||||
// #define CC_SOUND_CTRL_8 CC77
|
||||
// #define CC_SOUND_CTRL_9 CC78
|
||||
// #define CC_SOUND_CTRL_10 CC79
|
||||
// #define CC_GEN_PURPOSE_CTRL_5 CC80
|
||||
// #define CC_GEN_PURPOSE_CTRL_6 CC81
|
||||
// #define CC_GEN_PURPOSE_CTRL_7 CC82
|
||||
// #define CC_GEN_PURPOSE_CTRL_8 CC83
|
||||
// #define CC_PORTAMENTO_CTRL CC84
|
||||
// #define CC_ CC85
|
||||
// #define CC_ CC86
|
||||
// #define CC_ CC87
|
||||
// #define CC_ CC88
|
||||
// #define CC_ CC89
|
||||
#define CC_ASK_FOR_DATA CC90 |
||||
#define CC_BITCRUSH_OUT CC91 |
||||
// #define CC_EFFECT_2_DEPTH CC92
|
||||
// #define CC_EFFECT_3_DEPTH CC93
|
||||
// #define CC_EFFECT_4_DEPTH CC94
|
||||
// #define CC_EFFECT_5_DEPTH CC95
|
||||
// #define CC_DATA_INC CC96
|
||||
// #define CC_DATA_DEC CC97
|
||||
// #define CC_NRPN_LSB CC98
|
||||
// #define CC_NRPN_MSB CC99
|
||||
// #define CC_RPN_LSB CC100
|
||||
// #define CC_RPN_MSB CC101
|
||||
#define CC_OSC1_RANGE CC102 |
||||
#define CC_OSC1_WAVEFORM CC103 |
||||
#define CC_OSC2_RANGE CC104 |
||||
#define CC_OSC2_WAVEFORM CC105 |
||||
#define CC_OSC3_RANGE CC106 |
||||
#define CC_OSC3_WAVEFORM CC107 |
||||
#define CC_OSC3_CTRL CC108 |
||||
#define CC_FILTER_MOD CC109 |
||||
#define CC_FILTER_KEYTRACK_1 CC110 |
||||
#define CC_FILTER_KEYTRACK_2 CC111 |
||||
#define CC_TRANSPOSE CC112 |
||||
#define CC_FUNCTION CC113 |
||||
#define CC_NOISE_COLOR CC114 |
||||
#define CC_OSC_MOD CC115 |
||||
#define CC_DECAY_SW CC116 |
||||
#define CC_MOD_MIX_1 CC117 |
||||
#define CC_MOD_MIX_2 CC118 |
||||
#define CC_LFO_SHAPE CC119 |
||||
// #define CC_ALL_SOUND_OFF CC120
|
||||
// #define CC_RST_ALL_CTRL CC121
|
||||
// #define CC_LOCAL_CTRL_ON_OFF CC122
|
||||
// #define CC_ALL_NOTE_OFF CC123
|
||||
// #define CC_OMNI_MODE_OFF CC124
|
||||
// #define CC_OMNI_MODE_ON CC125
|
||||
// #define CC_MONO_MODE_ON CC126
|
||||
// #define CC_POLY_MODE_ON CC127
|
@ -0,0 +1,657 @@ |
||||
// Minimoog - Teensy
|
||||
/*
|
||||
* This program is part of a minimoog-like synthesizer based on teensy 4.0 |
||||
* Copyright (C) 2020 Pierre-Loup Martin |
||||
* |
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/* This program is a synthesizer very similar to the minimoog model D.
|
||||
* It is intended to run on a Teensy 4.0, using the PJRC audio library. |
||||
* It also uses two Arduino Mega boards to manage all the user inputs : |
||||
* keyboard, switches, potentiometers, etc. |
||||
* All user inputs are handled and send to the teensy board using midi commands |
||||
*/ |
||||
|
||||
#include <Audio.h> |
||||
#include <Wire.h> |
||||
#include <SPI.h> |
||||
#include <SD.h> |
||||
#include <SerialFlash.h> |
||||
|
||||
#include "audio_setup.h" |
||||
#include "defs.h" |
||||
|
||||
//#include "MIDI.h"
|
||||
|
||||
// constants
|
||||
const uint8_t KEYTRACK_MAX = 10; |
||||
|
||||
const uint8_t MAX_OCTAVE = 10; |
||||
const uint8_t FILTER_MAX_OCTAVE = 5; |
||||
|
||||
const float NOTE_MIDI_0 = 8.1757989156434; |
||||
const float NOTE_RATIO = 1.0594630943593; |
||||
|
||||
const float HALFTONE_TO_DC = (float)1 / (MAX_OCTAVE * 12); |
||||
const float FILTER_HALFTONE_TO_DC = (float)1 / (FILTER_MAX_OCTAVE * 12); |
||||
|
||||
const float MAX_MIX = 0.8; |
||||
|
||||
// variables
|
||||
|
||||
uint8_t midiChannel = 1; |
||||
|
||||
int8_t transposeOffset = 5; |
||||
|
||||
uint16_t glide = 0; |
||||
bool glideEn = 0; |
||||
|
||||
bool noteRetrigger = 1; |
||||
|
||||
bool filterKeyTrack1 = 0; |
||||
bool filterKeyTrack2 = 0; |
||||
|
||||
int8_t transpose = 0; |
||||
bool function = 0; |
||||
|
||||
bool oscMod = 0; |
||||
bool decay = 0; |
||||
|
||||
float filterDecay = 0; |
||||
float egDecay = 0; |
||||
|
||||
// Waveforms
|
||||
uint8_t waveforms[6] = {WAVEFORM_SINE, WAVEFORM_TRIANGLE, WAVEFORM_SAWTOOTH, |
||||
WAVEFORM_SAWTOOTH_REVERSE, WAVEFORM_SQUARE, WAVEFORM_PULSE}; |
||||
|
||||
// keyTrack
|
||||
uint8_t keyTrackIndex = 0; |
||||
uint8_t keyTrack[KEYTRACK_MAX] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
||||
|
||||
enum keyMode_t{ |
||||
KEY_FIRST = 0, |
||||
KEY_LAST, |
||||
KEY_LOWER, |
||||
KEY_UPPER, |
||||
}; |
||||
|
||||
keyMode_t keyMode = KEY_LAST; |
||||
|
||||
|
||||
//MIDI_CREATE_DEFAULT_INSTANCE();
|
||||
//MIDI_CREATE_INSTANCE(UsbTransport, sUsbTransport, usbMIDI);
|
||||
|
||||
|
||||
void setup() { |
||||
|
||||
// midi settings, start and callback usbMIDI.begin(1); usbMIDI.setHandleNoteOn(handleNoteOn) usbMIDI.setHandleNoteOff(handleNoteOff) usbMIDI.setHandlePitchBend(handlePitchBend) usbMIDI.setHandleControlChange(handleControlChange);
|
||||
|
||||
usbMIDI.setHandleNoteOn(handleNoteOn); |
||||
usbMIDI.setHandleNoteOff(handleNoteOff); |
||||
usbMIDI.setHandlePitchChange(handlePitchBend); |
||||
usbMIDI.setHandleControlChange(handleControlChange); |
||||
|
||||
Serial.begin(115200); |
||||
// Serial.println("started...");
|
||||
|
||||
AudioMemory(200); |
||||
|
||||
// audio settings
|
||||
// dc
|
||||
dcKeyTrack.amplitude(0.0); |
||||
dcPitchBend.amplitude(0.0); |
||||
dcFilterEnvelope.amplitude(1.0); |
||||
dcFilter.amplitude(0.0); |
||||
dcFilterKeyTrack.amplitude(0.0); |
||||
dcOsc3.amplitude(0.2); |
||||
dcLfoFreq.amplitude(0.0); |
||||
dcOscTune.amplitude(0.0); |
||||
dcOsc2Tune.amplitude(0.0); |
||||
dcOsc3Tune.amplitude(0.0); |
||||
dcPulse.amplitude(-0.95); |
||||
|
||||
|
||||
// amp
|
||||
ampPitchBend.gain(3 * HALFTONE_TO_DC * 2); |
||||
ampModWheel.gain(0); |
||||
ampPreFilter.gain(0.7); |
||||
ampModEg.gain(0.01); |
||||
ampOsc3Mod.gain(1); |
||||
|
||||
osc1Waveform.frequencyModulation(MAX_OCTAVE); |
||||
osc2Waveform.frequencyModulation(MAX_OCTAVE); |
||||
osc3Waveform.frequencyModulation(MAX_OCTAVE); |
||||
osc1Waveform.begin(1, NOTE_MIDI_0, WAVEFORM_TRIANGLE); |
||||
osc2Waveform.begin(1, NOTE_MIDI_0, WAVEFORM_SAWTOOTH); |
||||
osc3Waveform.begin(1, NOTE_MIDI_0, WAVEFORM_SQUARE); |
||||
|
||||
// noise
|
||||
whiteNoise.amplitude(1); |
||||
pinkNoise.amplitude(1); |
||||
|
||||
// LFO
|
||||
lfoWaveform.begin(1, 0.1, WAVEFORM_TRIANGLE); |
||||
lfoWaveform.frequencyModulation(11); |
||||
|
||||
// mixers
|
||||
mainTuneMixer.gain(0, 1); |
||||
mainTuneMixer.gain(1, 1); |
||||
mainTuneMixer.gain(2, 1); |
||||
mainTuneMixer.gain(3, 1); |
||||
osc2TuneMixer.gain(0, 1); |
||||
osc2TuneMixer.gain(1, 1); |
||||
osc3TuneMixer.gain(0, 1); |
||||
osc3TuneMixer.gain(1, 1); |
||||
|
||||
oscMixer.gain(0, 1); |
||||
oscMixer.gain(1, 0); |
||||
oscMixer.gain(2, 0); |
||||
oscMixer.gain(3, 0); |
||||
|
||||
globalMixer.gain(0, 1); |
||||
globalMixer.gain(1, 0); |
||||
|
||||
noiseMixer.gain(0, 1); |
||||
noiseMixer.gain(1, 0); |
||||
|
||||
osc3ControlMixer.gain(0, 1); |
||||
osc3ControlMixer.gain(1, 0); |
||||
|
||||
modMix1.gain(0, 0); |
||||
modMix1.gain(1, 1); |
||||
modMix2.gain(0, 1); |
||||
modMix2.gain(1, 0); |
||||
modMixer.gain(0, 1); |
||||
modMixer.gain(1, 0); |
||||
|
||||
filterMixer.gain(0, 0); |
||||
filterMixer.gain(1, 0); |
||||
filterMixer.gain(2, 1); |
||||
filterMixer.gain(3, 0); |
||||
|
||||
bandMixer.gain(0, 1); |
||||
bandMixer.gain(1, 0); |
||||
|
||||
// filter
|
||||
vcf.frequency(640); |
||||
vcf.resonance(0.7); |
||||
vcf.octaveControl(FILTER_MAX_OCTAVE); |
||||
|
||||
// envelopes
|
||||
mainEnvelope.delay(0); |
||||
mainEnvelope.attack(10); |
||||
mainEnvelope.hold(0); |
||||
mainEnvelope.decay(25); |
||||
mainEnvelope.sustain(0.9); |
||||
mainEnvelope.release(100); |
||||
|
||||
filterEnvelope.delay(0); |
||||
filterEnvelope.attack(200); |
||||
filterEnvelope.hold(0); |
||||
filterEnvelope.decay(100); |
||||
filterEnvelope.sustain(0.8); |
||||
filterEnvelope.release(50); |
||||
|
||||
bitCrushOutput.bits(16); |
||||
bitCrushOutput.sampleRate(44100.0); |
||||
|
||||
usbMIDI.sendControlChange(CC_ASK_FOR_DATA, 127, 1); |
||||
|
||||
} |
||||
|
||||
void loop() { |
||||
usbMIDI.read(); |
||||
} |
||||
|
||||
void noteOn(uint8_t note, uint8_t velocity, bool trigger = 1){ |
||||
float duration = (float)glideEn * (float)glide * 30.0; |
||||
float level = (float)note * HALFTONE_TO_DC; |
||||
float filterLevel = (float)note * FILTER_HALFTONE_TO_DC; |
||||
|
||||
AudioNoInterrupts(); |
||||
dcKeyTrack.amplitude(level, duration); |
||||
dcFilterKeyTrack.amplitude(filterLevel, duration); |
||||
if(trigger){ |
||||
filterEnvelope.noteOn(); |
||||
mainEnvelope.noteOn(); |
||||
} |
||||
AudioInterrupts(); |
||||
} |
||||
|
||||
void noteOff(){ |
||||
AudioNoInterrupts(); |
||||
filterEnvelope.noteOff(); |
||||
mainEnvelope.noteOff(); |
||||
AudioInterrupts(); |
||||
} |
||||
|
||||
int8_t keyTrackAddNote(uint8_t note){ |
||||
// We only keep count of a limited quantity of notes !
|
||||
if (keyTrackIndex >= KEYTRACK_MAX) return -1; |
||||
|
||||
keyTrack[keyTrackIndex] = note; |
||||
return keyTrackIndex++; |
||||
} |
||||
|
||||
int8_t keyTrackRemoveNote(uint8_t note){ |
||||
int8_t update = -1; |
||||
for(uint8_t i = 0; i < keyTrackIndex; ++i){ |
||||
if(keyTrack[i] == note){ |
||||
update = i; |
||||
keyTrackIndex--; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(update >= 0){ |
||||
for(uint8_t i = update; i < keyTrackIndex; ++i){ |
||||
keyTrack[i] = keyTrack[i + 1]; |
||||
} |
||||
} |
||||
|
||||
return update; |
||||
} |
||||
|
||||
void handleNoteOn(uint8_t channel, uint8_t note, uint8_t velocity){ |
||||
switch(keyMode){ |
||||
// When KEY_FIRST, we play the note only if there is not one already playing
|
||||
case KEY_FIRST: |
||||
if(keyTrackIndex != 0) return; |
||||
keyTrack[0] = note; |
||||
keyTrackIndex = 1; |
||||
noteOn(note, velocity); |
||||
// if(keyTrackAddNote(note) == 0) noteOn(note, velocity);
|
||||
break; |
||||
// When KEY_LAST, we play the new note anyway.
|
||||
case KEY_LAST: |
||||
keyTrack[0] = note; |
||||
if(keyTrackIndex != 0){ |
||||
noteOn(note, velocity, noteRetrigger); |
||||
} else { |
||||
noteOn(note, velocity); |
||||
} |
||||
keyTrackIndex = 1; |
||||
// if(keyTrackAddNote(note) == (keyTrackIndex - 1)) noteOn(note, velocity);
|
||||
break; |
||||
case KEY_LOWER: |
||||
case KEY_UPPER: |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
} |
||||
|
||||
void handleNoteOff(uint8_t channel, uint8_t note, uint8_t velocity){ |
||||
switch(keyMode){ |
||||
case KEY_FIRST: |
||||
/* if(keyTrackRemoveNote(note) == 0){
|
||||
noteOff(); |
||||
} |
||||
break; |
||||
*/ case KEY_LAST: |
||||
if(keyTrack[0] == note){ |
||||
keyTrackIndex = 0; |
||||
noteOff(); |
||||
} |
||||
/* if(keyTrackRemoveNote(note) == keyTrackIndex){
|
||||
noteOff(); |
||||
} |
||||
*/ break;
|
||||
case KEY_LOWER: |
||||
case KEY_UPPER: |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
} |
||||
|
||||
void handlePitchBend(uint8_t channel, int16_t bend){ |
||||
dcPitchBend.amplitude(((float)bend - 64) / 128); |
||||
} |
||||
|
||||
void handleControlChange(uint8_t channel, uint8_t command, uint8_t value){ |
||||
// Serial.println("control change");
|
||||
switch(command){ |
||||
case CC_MOD_WHEEL: // CC_1
|
||||
ampModWheel.gain((float)value / 12 / 127); |
||||
break; |
||||
case CC_MODULATION_MIX: // CC_3
|
||||
AudioNoInterrupts(); |
||||
modMixer.gain(0, (float)value / 127); |
||||
modMixer.gain(1, (127 - (float)value) / 127); |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_PORTAMENTO_TIME: |
||||
// CC_5
|
||||
glide = value; |
||||
break; |
||||
case CC_OSC_TUNE: |
||||
// CC_9
|
||||
dcOscTune.amplitude(HALFTONE_TO_DC * 2 * ((float)value - 64) / 127); |
||||
break; |
||||
case CC_OSC2_TUNE: |
||||
// CC_12
|
||||
dcOsc2Tune.amplitude(HALFTONE_TO_DC * 12 * 2 * ((float)value - 64) / 127); |
||||
break; |
||||
case CC_OSC3_TUNE: |
||||
// CC_13
|
||||
dcOsc3Tune.amplitude(HALFTONE_TO_DC * 12 * 2 * ((float)value - 64) / 127); |
||||
break; |
||||
case CC_OSC1_MIX: |
||||
// CC_14
|
||||
oscMixer.gain(0, MAX_MIX * (float)value / 127); |
||||
break; |
||||
case CC_OSC2_MIX: |
||||
// CC_15
|
||||
oscMixer.gain(1, MAX_MIX * (float)value / 127); |
||||
break; |
||||
case CC_OSC3_MIX: |
||||
// CC_16
|
||||
oscMixer.gain(2, MAX_MIX * (float)value / 127); |
||||
break; |
||||
case CC_NOISE_MIX: |
||||
// CC_17
|
||||
oscMixer.gain(3, MAX_MIX * (float)value / 127); |
||||
break; |
||||
case CC_FEEDBACK_MIX: |
||||
// CC_18
|
||||
globalMixer.gain(1, MAX_MIX * (float)value / 127); |
||||
break; |
||||
case CC_FILTER_BAND: |
||||
// CC_19
|
||||
AudioNoInterrupts(); |
||||
bandMixer.gain(0, ((float)value - 127) / 127); |
||||
bandMixer.gain(1, (float)value / 127); |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_FILTER_CUTOFF_FREQ: |
||||
// CC_20
|
||||
// vcf.frequency((float)value * 32);
|
||||
dcFilter.amplitude(((float)value - 64) / 127); |
||||
break; |
||||
case CC_FILTER_EMPHASIS: |
||||
// CC_21
|
||||
vcf.resonance(0.7 + (float)value / 29.53); |
||||
break; |
||||
case CC_FILTER_CONTOUR: |
||||
// CC_22
|
||||
filterMixer.gain(1, (float)value / 127); |
||||
case CC_FILTER_ATTACK: |
||||
// CC_23
|
||||
filterEnvelope.attack((float)value * 40); |
||||
break; |
||||
case CC_FILTER_DECAY: |
||||
// CC_24
|
||||
filterDecay = value * 40; |
||||
AudioNoInterrupts(); |
||||
filterEnvelope.decay(filterDecay); |
||||
if(decay) filterEnvelope.release(filterDecay); |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_FILTER_SUSTAIN: |
||||
// CC_25
|
||||
filterEnvelope.sustain((float)value / 127); |
||||
break; |
||||
case CC_FILTER_RELEASE: |
||||
// CC_26
|
||||
filterEnvelope.release((float)value / 127); |
||||
break; |
||||
case CC_EG_ATTACK: |
||||
// CC_27
|
||||
mainEnvelope.attack((float)value * 40); |
||||
break; |
||||
case CC_EG_DECAY: |
||||
// CC_28
|
||||
egDecay = value * 40; |
||||
AudioNoInterrupts(); |
||||
mainEnvelope.decay(egDecay); |
||||
if(decay) mainEnvelope.release(egDecay); |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_EG_SUSTAIN: |
||||
// CC_29
|
||||
mainEnvelope.sustain((float)value / 127); |
||||
break; |
||||
case CC_LFO_RATE: |
||||
// CC_31
|
||||
dcLfoFreq.amplitude((float)value / 127); |
||||
break; |
||||
case CC_MOD_WHEEL_LSB: |
||||
// CC_33
|
||||
break; |
||||
case CC_MODULATION_MIX_LSB: |
||||
// CC_35
|
||||
break; |
||||
case CC_PORTAMENTO_TIME_LSB: |
||||
// CC_37
|
||||
break; |
||||
case CC_OSC_TUNE_LSB: |
||||
// CC_41
|
||||
break; |
||||
case CC_OSC2_TUNE_LSB: |
||||
// CC_44
|
||||
break; |
||||
case CC_OSC3_TUNE_LSB: |
||||
// CC_45
|
||||
break; |
||||
case CC_OSC1_MIX_LSB: |
||||
// CC_46
|
||||
break; |
||||
case CC_OSC2_MIX_LSB: |
||||
// CC_47
|
||||
break; |
||||
case CC_OSC3_MIX_LSB: |
||||
// CC_48
|
||||
break; |
||||
case CC_NOISE_MIX_LSB: |
||||
// CC_49
|
||||
break; |
||||
case CC_FEEDBACK_MIX_LSB: |
||||
// CC_50
|
||||
break; |
||||
case CC_FILTER_BAND_LSB: |
||||
// CC_51
|
||||
break; |
||||
case CC_FILTER_CUTOFF_FREQ_LSB: |
||||
// CC_52
|
||||
break; |
||||
case CC_FILTER_EMPHASIS_LSB: |
||||
// CC_53
|
||||
break; |
||||
case CC_FILTER_CONTOUR_LSB: |
||||
// CC_54
|
||||
break; |
||||
case CC_FILTER_ATTACK_LSB: |
||||
// CC_55
|
||||
break; |
||||
case CC_FILTER_DECAY_LSB: |
||||
// CC_56
|
||||
break; |
||||
case CC_FILTER_SUSTAIN_LSB: |
||||
// CC_57
|
||||
break; |
||||
case CC_EG_ATTACK_LSB: |
||||
// CC_58
|
||||
break; |
||||
case CC_EG_DECAY_LSB: |
||||
// CC_59
|
||||
break; |
||||
case CC_EG_SUSTAIN_LSB: |
||||
// CC_60
|
||||
break; |
||||
case CC_LFO_RATE_LSB: |
||||
// CC_62
|
||||
break; |
||||
case CC_PORTAMENTO_ON_OFF: |
||||
// CC_65
|
||||
if(value > 63){ |
||||
glideEn = 1; |
||||
} else { |
||||
glideEn = 0; |
||||
} |
||||
break; |
||||
case CC_BITCRUSH_OUT: |
||||
// CC_91
|
||||
bitCrushOutput.bits(value); |
||||
break; |
||||
case CC_OSC1_RANGE: |
||||
// CC_102
|
||||
osc1Waveform.frequency(NOTE_MIDI_0 / pow(2, value)); |
||||
break; |
||||
case CC_OSC1_WAVEFORM: |
||||
// CC_103
|
||||
osc1Waveform.begin(waveforms[value]); |
||||
break; |
||||
case CC_OSC2_RANGE: |
||||
// CC_104
|
||||
osc2Waveform.frequency(NOTE_MIDI_0 / pow(2, value)); |
||||
break; |
||||
case CC_OSC2_WAVEFORM: |
||||
// CC_105
|
||||
osc2Waveform.begin(waveforms[value]); |
||||
break; |
||||
case CC_OSC3_RANGE: |
||||
// CC_106
|
||||
osc3Waveform.frequency(NOTE_MIDI_0 / pow(2, value)); |
||||
break; |
||||
case CC_OSC3_WAVEFORM: |
||||
// CC_107
|
||||
osc3Waveform.begin(waveforms[value]); |
||||
break; |
||||
case CC_OSC3_CTRL: |
||||
// CC_108
|
||||
AudioNoInterrupts(); |
||||
if(value > 63){ |
||||
osc3ControlMixer.gain(0, 1); |
||||
osc3ControlMixer.gain(1, 0); |
||||
} else { |
||||
osc3ControlMixer.gain(0, 0); |
||||
osc3ControlMixer.gain(1, 1);
|
||||
} |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_FILTER_MOD: |
||||
// CC_109
|
||||
if(value > 63){ |
||||
filterMixer.gain(0, 2); |
||||
} else { |
||||
filterMixer.gain(0, 0); |
||||
} |
||||
break; |
||||
case CC_FILTER_KEYTRACK_1: |
||||
// CC_110
|
||||
if(value > 63){ |
||||
filterKeyTrack1 = 1; |
||||
} else { |
||||
filterKeyTrack1 = 0; |
||||
} |
||||
filterMixer.gain(3, (filterKeyTrack1 * 0.333 + filterKeyTrack2 * 0.667)); |
||||
break; |
||||
case CC_FILTER_KEYTRACK_2: |
||||
// CC_111
|
||||
if(value > 63){ |
||||
filterKeyTrack2 = 1; |
||||
} else { |
||||
filterKeyTrack2 = 0; |
||||
} |
||||
filterMixer.gain(3, (filterKeyTrack1 * 0.333 + filterKeyTrack2 * 0.667)); |
||||
break; |
||||
case CC_TRANSPOSE: |
||||
// CC_112
|
||||
if(value > 63){ |
||||
transpose++; |
||||
if (transpose > 2) transpose = 2; |
||||
} else { |
||||
transpose--; |
||||
if(transpose < -2) transpose = -2; |
||||
} |
||||
break; |
||||
case CC_FUNCTION: |
||||
// CC_113
|
||||
if(value > 63){ |
||||
function = 1; |
||||
} else { |
||||
function = 0; |
||||
} |
||||
break; |
||||
case CC_NOISE_COLOR: |
||||
// CC_114
|
||||
AudioNoInterrupts(); |
||||
if(value > 0){ |
||||
noiseMixer.gain(0, 1); |
||||
noiseMixer.gain(1, 0); |
||||
} else { |
||||
noiseMixer.gain(0, 0); |
||||
noiseMixer.gain(1, 1); |
||||
} |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_OSC_MOD: |
||||
// CC_115
|
||||
if(value > 63){ |
||||
oscMod = 1; |
||||
mainTuneMixer.gain(3, 1); |
||||
} else { |
||||
oscMod = 0; |
||||
mainTuneMixer.gain(3, 0); |
||||
} |
||||
break; |
||||
case CC_DECAY_SW: |
||||
// CC_116
|
||||
AudioNoInterrupts(); |
||||
if(value > 63){ |
||||
decay = 1; |
||||
filterEnvelope.release(filterDecay); |
||||
mainEnvelope.release(egDecay); |
||||
} else { |
||||
decay = 0; |
||||
filterEnvelope.release(0.0); |
||||
mainEnvelope.release(0.0); |
||||
} |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_MOD_MIX_1: |
||||
// CC_117
|
||||
AudioNoInterrupts(); |
||||
if(value > 63){ |
||||
modMix1.gain(0, 0); |
||||
modMix1.gain(1, 1); |
||||
} else { |
||||
modMix1.gain(0, 1); |
||||
modMix1.gain(1, 0); |
||||
} |
||||
AudioInterrupts(); |
||||
break; |
||||
case CC_MOD_MIX_2: |
||||
// CC_118
|
||||
AudioNoInterrupts(); |
||||
if(value > 63){ |
||||
modMix2.gain(0, 0); |
||||
modMix2.gain(1, 1); |
||||
} else { |
||||
modMix2.gain(0, 1); |
||||
modMix2.gain(1, 0); |
||||
} |
||||
AudioInterrupts(); |
||||
break; |
||||
/* case CC_LFO_SHAPE: // CC_119
|
||||
if(value > 63){ |
||||
} else { |
||||
} |
||||
break; |
||||
*/ default: |
||||
break; |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,34 @@ |
||||
0 5V |
||||
1 GND |
||||
2 modulation mix |
||||
3 glide |
||||
4 osc1 range |
||||
5 osc2 range |
||||
6 osc3 range |
||||
7 osc1 waveform |
||||
8 osc2 waveform |
||||
9 osc3 waveform |
||||
10 osc1 mix |
||||
11 osc2 mix |
||||
12 osc3 mix |
||||
13 noise mix |
||||
14 feedback mix |
||||
15 modulation mix 1 |
||||
16 modulation mix 2 |
||||
17 osc modulation |
||||
18 osc3 ctrl |
||||
19 transpose + |
||||
20 transpose - |
||||
21 osc1 mix sw |
||||
22 osc2 mix sw |
||||
23 osc3 mix sw |
||||
24 noise mix sw |
||||
25 feedback mix sw |
||||
26 noise color |
||||
27 mega 2 rx from teensy |
||||
28 mega 2 tx to teensy |
||||
29 mega 2 reset |
||||
30 |
||||
31 |
||||
32 |
||||
33 |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 204 KiB |
Loading…
Reference in new issue