├── Arcus ├── Arcus-Top.pdf ├── Arcus-bottom.pdf ├── Final Connections.png ├── name.c └── Arcus.ino ├── Cirrus ├── Cirrus.pdf ├── name.c ├── synth_sine.h ├── synth_sine.cpp ├── Cirrus-case-final.svg └── Cirrus.ino ├── Stratus ├── stratus.pdf ├── name.c ├── Stratus-Case.svg └── Stratus.ino └── Nimbus ├── nimbusBox.svg └── Nimbus.ino /Arcus/Arcus-Top.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otem/RDEI/HEAD/Arcus/Arcus-Top.pdf -------------------------------------------------------------------------------- /Cirrus/Cirrus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otem/RDEI/HEAD/Cirrus/Cirrus.pdf -------------------------------------------------------------------------------- /Stratus/stratus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otem/RDEI/HEAD/Stratus/stratus.pdf -------------------------------------------------------------------------------- /Arcus/Arcus-bottom.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otem/RDEI/HEAD/Arcus/Arcus-bottom.pdf -------------------------------------------------------------------------------- /Arcus/Final Connections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otem/RDEI/HEAD/Arcus/Final Connections.png -------------------------------------------------------------------------------- /Arcus/name.c: -------------------------------------------------------------------------------- 1 | // To give your project a unique name, this code must be 2 | // placed into a .c file (its own tab). It can not be in 3 | // a .cpp file or your main sketch (the .ino file). 4 | 5 | #include "usb_names.h" 6 | 7 | // Edit these lines to create your own name. The length must 8 | // match the number of characters in your custom name. 9 | 10 | #define MIDI_NAME {'A','r','c','u','s'} 11 | #define MIDI_NAME_LEN 5 12 | 13 | // Do not change this part. This exact format is required by USB. 14 | 15 | struct usb_string_descriptor_struct usb_string_product_name = { 16 | 2 + MIDI_NAME_LEN * 2, 17 | 3, 18 | MIDI_NAME 19 | }; -------------------------------------------------------------------------------- /Cirrus/name.c: -------------------------------------------------------------------------------- 1 | // To give your project a unique name, this code must be 2 | // placed into a .c file (its own tab). It can not be in 3 | // a .cpp file or your main sketch (the .ino file). 4 | 5 | #include "usb_names.h" 6 | 7 | // Edit these lines to create your own name. The length must 8 | // match the number of characters in your custom name. 9 | 10 | #define MIDI_NAME {'C','i','r','r','u','s'} 11 | #define MIDI_NAME_LEN 6 12 | 13 | // Do not change this part. This exact format is required by USB. 14 | 15 | struct usb_string_descriptor_struct usb_string_product_name = { 16 | 2 + MIDI_NAME_LEN * 2, 17 | 3, 18 | MIDI_NAME 19 | }; 20 | -------------------------------------------------------------------------------- /Stratus/name.c: -------------------------------------------------------------------------------- 1 | // To give your project a unique name, this code must be 2 | // placed into a .c file (its own tab). It can not be in 3 | // a .cpp file or your main sketch (the .ino file). 4 | 5 | #include "usb_names.h" 6 | 7 | // Edit these lines to create your own name. The length must 8 | // match the number of characters in your custom name. 9 | 10 | #define MIDI_NAME {'S','t','r','a','t','u','s'} 11 | #define MIDI_NAME_LEN 7 12 | 13 | // Do not change this part. This exact format is required by USB. 14 | 15 | struct usb_string_descriptor_struct usb_string_product_name = { 16 | 2 + MIDI_NAME_LEN * 2, 17 | 3, 18 | MIDI_NAME 19 | }; 20 | -------------------------------------------------------------------------------- /Cirrus/synth_sine.h: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | //My Changes 28 | ///https://forum.pjrc.com/threads/33720-Teensy-FM-Synthesis-Problems-not-enough-modulation 29 | 30 | #ifndef synth_sine_h_ 31 | #define synth_sine_h_ 32 | 33 | #include "Arduino.h" 34 | #include "AudioStream.h" 35 | #include "arm_math.h" 36 | 37 | // TODO: investigate making a high resolution sine wave 38 | // using Taylor series expansion. 39 | // http://www.musicdsp.org/showone.php?id=13 40 | 41 | class AudioSynthWaveformSine : public AudioStream 42 | { 43 | public: 44 | AudioSynthWaveformSine() : AudioStream(0, NULL), magnitude(16384) {} 45 | void frequency(float freq) { 46 | if (freq < 0.0) freq = 0.0; 47 | else if (freq > AUDIO_SAMPLE_RATE_EXACT/2) freq = AUDIO_SAMPLE_RATE_EXACT/2; 48 | phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT); 49 | } 50 | void phase(float angle) { 51 | if (angle < 0.0) angle = 0.0; 52 | else if (angle > 360.0) { 53 | angle = angle - 360.0; 54 | if (angle >= 360.0) return; 55 | } 56 | phase_accumulator = angle * (4294967296.0 / 360.0); 57 | } 58 | void amplitude(float n) { 59 | if (n < 0) n = 0; 60 | else if (n > 1.0) n = 1.0; 61 | magnitude = n * 65536.0; 62 | } 63 | virtual void update(void); 64 | private: 65 | uint32_t phase_accumulator; 66 | uint32_t phase_increment; 67 | int32_t magnitude; 68 | }; 69 | 70 | 71 | class AudioSynthWaveformSineHires : public AudioStream 72 | { 73 | public: 74 | AudioSynthWaveformSineHires() : AudioStream(0, NULL), magnitude(16384) {} 75 | void frequency(float freq) { 76 | if (freq < 0.0) freq = 0.0; 77 | else if (freq > AUDIO_SAMPLE_RATE_EXACT/2) freq = AUDIO_SAMPLE_RATE_EXACT/2; 78 | phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT); 79 | } 80 | void phase(float angle) { 81 | if (angle < 0.0) angle = 0.0; 82 | else if (angle > 360.0) { 83 | angle = angle - 360.0; 84 | if (angle >= 360.0) return; 85 | } 86 | phase_accumulator = angle * (4294967296.0 / 360.0); 87 | } 88 | void amplitude(float n) { 89 | if (n < 0) n = 0; 90 | else if (n > 1.0) n = 1.0; 91 | magnitude = n * 65536.0; 92 | } 93 | virtual void update(void); 94 | private: 95 | uint32_t phase_accumulator; 96 | uint32_t phase_increment; 97 | int32_t magnitude; 98 | }; 99 | 100 | 101 | class AudioSynthWaveformSineModulated : public AudioStream 102 | { 103 | public: 104 | AudioSynthWaveformSineModulated() : AudioStream(1, inputQueueArray), magnitude(16384) {} 105 | // maximum unmodulated carrier frequency is 11025 Hz 106 | // input = +1.0 doubles carrier 107 | // input = -1.0 DC output 108 | void frequency(float freq) { 109 | if (freq < 0.0) freq = 0.0; 110 | else if (freq > AUDIO_SAMPLE_RATE_EXACT/4) freq = AUDIO_SAMPLE_RATE_EXACT/4; 111 | phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT); 112 | } 113 | void phase(float angle) { 114 | if (angle < 0.0) angle = 0.0; 115 | else if (angle > 360.0) { 116 | angle = angle - 360.0; 117 | if (angle >= 360.0) return; 118 | } 119 | phase_accumulator = angle * (4294967296.0 / 360.0); 120 | } 121 | void amplitude(float n) { 122 | if (n < 0) n = 0; 123 | else if (n > 1.0) n = 1.0; 124 | magnitude = n * 65536.0; 125 | } 126 | void mod_index(float n) { 127 | if (n < 0) n = 0; 128 | else if (n > 65535.0) n = 65535.0; 129 | _mod_index = n * 65536.0; 130 | } 131 | virtual void update(void); 132 | private: 133 | uint32_t phase_accumulator; 134 | uint32_t phase_increment; 135 | audio_block_t *inputQueueArray[1]; 136 | int32_t magnitude; 137 | int32_t _mod_index; 138 | }; 139 | 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /Cirrus/synth_sine.cpp: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | //My Changes 28 | ///https://forum.pjrc.com/threads/33720-Teensy-FM-Synthesis-Problems-not-enough-modulation 29 | 30 | #include 31 | #include "synth_sine.h" 32 | #include "utility/dspinst.h" 33 | 34 | // data_waveforms.c 35 | extern "C" { 36 | extern const int16_t AudioWaveformSine[257]; 37 | } 38 | 39 | 40 | void AudioSynthWaveformSine::update(void) 41 | { 42 | audio_block_t *block; 43 | uint32_t i, ph, inc, index, scale; 44 | int32_t val1, val2; 45 | 46 | if (magnitude) { 47 | block = allocate(); 48 | if (block) { 49 | ph = phase_accumulator; 50 | inc = phase_increment; 51 | for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { 52 | index = ph >> 24; 53 | val1 = AudioWaveformSine[index]; 54 | val2 = AudioWaveformSine[index+1]; 55 | scale = (ph >> 8) & 0xFFFF; 56 | val2 *= scale; 57 | val1 *= 0x10000 - scale; 58 | #if defined(KINETISK) 59 | block->data[i] = multiply_32x32_rshift32(val1 + val2, magnitude); 60 | #elif defined(KINETISL) 61 | block->data[i] = (((val1 + val2) >> 16) * magnitude) >> 16; 62 | #endif 63 | ph += inc; 64 | } 65 | phase_accumulator = ph; 66 | transmit(block); 67 | release(block); 68 | return; 69 | } 70 | } 71 | phase_accumulator += phase_increment * AUDIO_BLOCK_SAMPLES; 72 | } 73 | 74 | 75 | 76 | 77 | 78 | #if defined(KINETISK) 79 | // High accuracy 11th order Taylor Series Approximation 80 | // input is 0 to 0xFFFFFFFF, representing 0 to 360 degree phase 81 | // output is 32 bit signed integer, top 25 bits should be very good 82 | static int32_t taylor(uint32_t ph) 83 | { 84 | int32_t angle, sum, p1, p2, p3, p5, p7, p9, p11; 85 | 86 | if (ph >= 0xC0000000 || ph < 0x40000000) { // ph: 0.32 87 | angle = (int32_t)ph; // valid from -90 to +90 degrees 88 | } else { 89 | angle = (int32_t)(0x80000000u - ph); // angle: 2.30 90 | } 91 | p1 = multiply_32x32_rshift32_rounded(angle, 1686629713) << 2; // p1: 2.30 92 | p2 = multiply_32x32_rshift32_rounded(p1, p1) << 1; // p2: 3.29 93 | p3 = multiply_32x32_rshift32_rounded(p2, p1) << 2; // p3: 3.29 94 | sum = multiply_subtract_32x32_rshift32_rounded(p1, p3, 1431655765); // sum: 2.30 95 | p5 = multiply_32x32_rshift32_rounded(p3, p2); // p5: 6.26 96 | sum = multiply_accumulate_32x32_rshift32_rounded(sum, p5, 572662306); 97 | p7 = multiply_32x32_rshift32_rounded(p5, p2); // p7: 9.23 98 | sum = multiply_subtract_32x32_rshift32_rounded(sum, p7, 109078534); 99 | p9 = multiply_32x32_rshift32_rounded(p7, p2); // p9: 12.20 100 | sum = multiply_accumulate_32x32_rshift32_rounded(sum, p9, 12119837); 101 | p11 = multiply_32x32_rshift32_rounded(p9, p2); // p11: 15.17 102 | sum = multiply_subtract_32x32_rshift32_rounded(sum, p11, 881443); 103 | return sum <<= 1; // return: 1.31 104 | } 105 | #endif 106 | 107 | 108 | void AudioSynthWaveformSineHires::update(void) 109 | { 110 | #if defined(KINETISK) 111 | audio_block_t *msw, *lsw; 112 | uint32_t i, ph, inc; 113 | int32_t val; 114 | 115 | if (magnitude) { 116 | msw = allocate(); 117 | lsw = allocate(); 118 | if (msw && lsw) { 119 | ph = phase_accumulator; 120 | inc = phase_increment; 121 | for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { 122 | val = taylor(ph); 123 | msw->data[i] = val >> 16; 124 | lsw->data[i] = val & 0xFFFF; 125 | ph += inc; 126 | } 127 | phase_accumulator = ph; 128 | transmit(msw, 0); 129 | release(msw); 130 | transmit(lsw, 1); 131 | release(lsw); 132 | return; 133 | } else { 134 | if (msw) release(msw); 135 | if (lsw) release(lsw); 136 | } 137 | } 138 | phase_accumulator += phase_increment * AUDIO_BLOCK_SAMPLES; 139 | #endif 140 | } 141 | 142 | 143 | 144 | #if defined(KINETISK) 145 | 146 | void AudioSynthWaveformSineModulated::update(void) 147 | { 148 | audio_block_t *block, *modinput; 149 | uint32_t i, ph, inc, index, scale; 150 | int32_t val1, val2; 151 | int32_t mod; 152 | 153 | modinput = receiveReadOnly(); 154 | ph = phase_accumulator; 155 | inc = phase_increment; 156 | block = allocate(); 157 | if (!block) { 158 | // unable to allocate memory, so we'll send nothing 159 | if (modinput) { 160 | // but if we got modulation data, update the phase 161 | for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { 162 | mod = signed_multiply_32x16b(_mod_index, modinput->data[i]); 163 | ph += inc + mod; // (multiply_32x32_rshift32(inc, mod << 16) << 1); 164 | } 165 | release(modinput); 166 | } else { 167 | ph += phase_increment * AUDIO_BLOCK_SAMPLES; 168 | } 169 | phase_accumulator = ph; 170 | return; 171 | } 172 | if (modinput) { 173 | for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { 174 | index = ph >> 24; 175 | val1 = AudioWaveformSine[index]; 176 | val2 = AudioWaveformSine[index+1]; 177 | scale = (ph >> 8) & 0xFFFF; 178 | val2 *= scale; 179 | val1 *= 0x10000 - scale; 180 | //block->data[i] = (((val1 + val2) >> 16) * magnitude) >> 16; 181 | block->data[i] = multiply_32x32_rshift32(val1 + val2, magnitude); 182 | // -32768 = no phase increment 183 | // 32767 = double phase increment 184 | mod = signed_multiply_32x16b(_mod_index, modinput->data[i]); 185 | ph += inc + mod; // (multiply_32x32_rshift32(inc, mod << 16) << 1); 186 | //ph += inc + (((int64_t)inc * (mod << 16)) >> 31); 187 | } 188 | release(modinput); 189 | } else { 190 | ph = phase_accumulator; 191 | inc = phase_increment; 192 | for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) { 193 | index = ph >> 24; 194 | val1 = AudioWaveformSine[index]; 195 | val2 = AudioWaveformSine[index+1]; 196 | scale = (ph >> 8) & 0xFFFF; 197 | val2 *= scale; 198 | val1 *= 0x10000 - scale; 199 | block->data[i] = multiply_32x32_rshift32(val1 + val2, magnitude); 200 | ph += inc; 201 | } 202 | } 203 | phase_accumulator = ph; 204 | transmit(block); 205 | release(block); 206 | } 207 | 208 | #elif defined(KINETISL) 209 | 210 | void AudioSynthWaveformSineModulated::update(void) 211 | { 212 | audio_block_t *block; 213 | 214 | block = receiveReadOnly(); 215 | if (block) release(block); 216 | } 217 | 218 | #endif 219 | 220 | -------------------------------------------------------------------------------- /Cirrus/Cirrus-case-final.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 | 33 | 36 | 39 | 42 | 45 | 46 | 47 | 48 | 51 | 54 | 57 | 60 | 63 | 64 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 92 | 94 | 95 | 99 | 100 | 101 | 105 | 106 | 107 | 109 | Decor = 1.25 110 | Blades = 0.8 111 | 112 | 116 | 118 | 121 | 123 | 126 | 128 | 131 | 133 | 136 | 138 | 141 | 143 | 146 | 148 | 151 | 153 | 156 | 157 | 158 | 159 | 161 | 164 | 167 | 170 | 173 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /Stratus/Stratus-Case.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 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 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 105 | 106 | 110 | 114 | 119 | 124 | 125 | -------------------------------------------------------------------------------- /Nimbus/nimbusBox.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 38 | 40 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 63 | jack pocket: 2.5mm 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 102 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 131 | 134 | 138 | 139 | 140 | 141 | 142 | 143 | 145 | 151 | 152 | 153 | 155 | 161 | 167 | 168 | 169 | 171 | 177 | 179 | 180 | 181 | 183 | 185 | 187 | 188 | VCO 189 | 193 | 197 | 201 | 205 | 207 | 209 | 211 | 212 | -------------------------------------------------------------------------------- /Stratus/Stratus.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int chip_pin_one = 38; 6 | int chip_pin_two = 39; 7 | int gatePins[4] = {17,16,15,14}; 8 | //Encoder Btn 9 | int extBtnPins[3] = {A21, A22,A11}; 10 | int extBtnSt[3]; 11 | int extBtnStPrev[3]; 12 | int btnThresh[3] = {290,390,390}; 13 | bool tempBtnDown; 14 | bool gateBtnDown; 15 | bool noteDown; 16 | unsigned long initTmStp; 17 | unsigned long gateBtnTmStp; 18 | bool seqLengthMode; 19 | //Encoder 20 | int tempEncRotPin1 = 21; 21 | int tempEncRotPin2 = 20; 22 | volatile int tempLastEncoded = 0; 23 | volatile long tempEncVal = 500; 24 | int tempEncoded; 25 | //Encoder 2 26 | int seqEncRotPin1 = 19; 27 | int seqEncRotPin2 = 18; 28 | volatile int seqLastEncoded; 29 | volatile long seqEncVal; 30 | int seqEncoded; 31 | 32 | int btnAnim; 33 | unsigned long btnAnimTmStp; 34 | bool randomizedRow[4] = {false,false,false,false}; 35 | bool recAutomation; 36 | 37 | unsigned long blkTmr; 38 | unsigned long blkTmrM; 39 | int clkInPin = 22; 40 | int seqSelPin = 23; 41 | int analogPin = A10; 42 | int analogValue; 43 | int analogValueLag; 44 | 45 | int trigSetInput; 46 | int prevTrigSetInput; 47 | 48 | 49 | bool internalClock; 50 | int seqStep = 31; 51 | bool gateMutes[4]; 52 | bool anyMuteDown; 53 | 54 | int gateSteps[4]; 55 | int seqLengths[4] = {31,31,31,31}; 56 | 57 | int seqSpeeds[4] = {8,4,2,1}; 58 | int speedIndex[4] = {3,3,3,3}; 59 | 60 | int seqLengthLedRow; 61 | int seqLengthLedCol; 62 | 63 | int prevSeqStep = 1; 64 | bool seqRunning; 65 | unsigned long gateSentTime = -3000; 66 | unsigned long prevGateSentTime; 67 | unsigned long extrGtSntTm; 68 | int cvStep; 69 | 70 | int trigSet; 71 | //[pattern][steps][gate] 72 | bool trigs[4][32][4]; 73 | int cvVals[4][32][4]; 74 | 75 | bool cpyTrigs[4][32][4]; 76 | int cpyCvVals[4][32][4]; 77 | 78 | int gateOutNumber; 79 | int seqPageMath[4] = {0,8,16,24}; 80 | unsigned long menuTimeStp; 81 | bool menuSelect; 82 | bool menuOpen; 83 | 84 | unsigned long prevMetroTime; 85 | unsigned long intervalTime = 500; 86 | unsigned long intervalTmStp; 87 | 88 | unsigned long clearPgTmStp[4]; 89 | bool gatesMutDwn[4]; 90 | bool allGatesOff = true; 91 | 92 | //slave MIDI 93 | byte counter; 94 | byte CLOCK = 248; 95 | byte START = 250; 96 | byte CONTINUE = 251; 97 | byte STOP = 252; 98 | 99 | 100 | #define NUM_LED_COLUMNS (9) 101 | #define NUM_LED_ROWS (4) 102 | #define NUM_BTN_COLUMNS (9) 103 | #define NUM_BTN_ROWS (4) 104 | #define NUM_COLORS (1) 105 | 106 | #define MAX_DEBOUNCE (3) 107 | 108 | // Global variables 109 | static bool LED_buffer[NUM_LED_COLUMNS][NUM_LED_ROWS]; 110 | static const uint8_t btncolumnpins[NUM_BTN_COLUMNS] = {9, 12, 25, 27, 29, 31, 33, 35, 37}; 111 | static const uint8_t btnrowpins[NUM_BTN_ROWS] = {6,4,2,0}; 112 | static const uint8_t ledcolumnpins[NUM_LED_COLUMNS] = {8, 10, 24, 26, 28, 30, 32, 34, 36}; 113 | static const uint8_t ledRows[NUM_LED_ROWS] = {7,5,3,1}; 114 | 115 | static int8_t debounce_count[NUM_BTN_COLUMNS][NUM_BTN_ROWS]; 116 | 117 | static void setuppins(){ 118 | uint8_t i; 119 | // LED columns 120 | for (i = 0; i < NUM_LED_COLUMNS; i++){ 121 | pinMode(ledcolumnpins[i], OUTPUT); 122 | digitalWrite(ledcolumnpins[i], HIGH); 123 | } 124 | // button columns 125 | for (i = 0; i < NUM_BTN_COLUMNS; i++){ 126 | pinMode(btncolumnpins[i], OUTPUT); 127 | digitalWrite(btncolumnpins[i], HIGH); 128 | } 129 | // button row input lines 130 | for (i = 0; i < NUM_BTN_ROWS; i++){ 131 | pinMode(btnrowpins[i], INPUT_PULLUP); 132 | } 133 | // LED drive lines 134 | for (i = 0; i < NUM_LED_ROWS; i++){ 135 | pinMode(ledRows[i], OUTPUT); 136 | digitalWrite(ledRows[i], LOW); 137 | } 138 | // Initialize the debounce counter arrayz 139 | for (uint8_t i = 0; i < NUM_BTN_COLUMNS; i++){ 140 | for (uint8_t j = 0; j < NUM_BTN_ROWS; j++){ 141 | debounce_count[i][j] = 0; 142 | } 143 | } 144 | } 145 | 146 | void setup() { 147 | Serial.begin(9600); 148 | usbMIDI.setHandleRealTimeSystem(RealTimeSystem); 149 | pinMode(chip_pin_one, OUTPUT); 150 | pinMode(chip_pin_two, OUTPUT); 151 | SPI.begin(); 152 | setuppins(); 153 | for(int i=0; i<4; i++){ 154 | pinMode(gatePins[i], OUTPUT); 155 | } 156 | //gate inputs 157 | pinMode(clkInPin, INPUT); 158 | pinMode(seqSelPin, INPUT); 159 | //CV 160 | //analogWriteResolution(12); 161 | //CLKIN 162 | attachInterrupt(clkInPin, pulseInput, RISING); 163 | //ENCODER 164 | pinMode(tempEncRotPin1, INPUT); 165 | pinMode(tempEncRotPin2, INPUT); 166 | digitalWrite(tempEncRotPin1, HIGH); 167 | digitalWrite(tempEncRotPin2, HIGH); 168 | attachInterrupt(tempEncRotPin1, updateTempo, CHANGE); 169 | attachInterrupt(tempEncRotPin2, updateTempo, CHANGE); 170 | //ENCODER 2 171 | pinMode(seqEncRotPin1, INPUT); 172 | pinMode(seqEncRotPin2, INPUT); 173 | digitalWrite(seqEncRotPin1, HIGH); 174 | digitalWrite(seqEncRotPin2, HIGH); 175 | attachInterrupt(seqEncRotPin1, updatePattern, CHANGE); 176 | attachInterrupt(seqEncRotPin2, updatePattern, CHANGE); 177 | trigSetInput = (analogRead(seqSelPin)-260)/100; 178 | trigSetInput = constrain(trigSetInput, 0, 3); 179 | prevTrigSetInput = trigSetInput; 180 | analogValue = analogRead(analogPin); 181 | analogValueLag = analogValue; 182 | loadPreset(); 183 | } 184 | 185 | void pulseInput(){ 186 | intervalTime = millis() - extrGtSntTm; 187 | seqRunning = true; 188 | seqStep++; 189 | for(int i=0; i<4; i++){ 190 | if(seqStep % seqSpeeds[speedIndex[i]] == 0){ 191 | if(randomizedRow[i]){ 192 | gateSteps[i] = random(0, seqLengths[i]); 193 | }else{ 194 | gateSteps[i]++; 195 | } 196 | } 197 | } 198 | if(seqStep > 2){ 199 | intervalTime = millis() - gateSentTime; 200 | } 201 | internalClock = false; 202 | } 203 | 204 | void updateTempo(){ 205 | int MSB = digitalRead(tempEncRotPin1); //MSB = most significant bit 206 | int LSB = digitalRead(tempEncRotPin2); //LSB = least significant bit 207 | tempEncoded = (MSB << 1) |LSB; //converting the 2 pin value to single number 208 | int sum = (tempLastEncoded << 2) | tempEncoded; //adding it to the previous encoded value 209 | if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) tempEncVal ++; 210 | if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) tempEncVal --; 211 | if (tempEncVal < 0){ 212 | tempEncVal = 0; 213 | } 214 | if(tempEncVal > 1000) tempEncVal = 1000; 215 | intervalTime = (1000 - tempEncVal) + 20; 216 | tempLastEncoded = tempEncoded; //store this value for next time 217 | } 218 | 219 | void updatePattern(){ 220 | int MSB = digitalRead(seqEncRotPin1); //MSB = most significant bit 221 | int LSB = digitalRead(seqEncRotPin2); //LSB = least significant bit 222 | seqEncoded = (MSB << 1) |LSB; //converting the 2 pin value to single number 223 | int sum = (seqLastEncoded << 2) | seqEncoded; //adding it to the previous encoded value 224 | if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) seqEncVal ++; 225 | if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) seqEncVal --; 226 | if (seqEncVal < 0){ 227 | seqEncVal = 0; 228 | } 229 | if(seqLengthMode){ 230 | if(seqEncVal > 124) seqEncVal = 124; 231 | lightsOut(); 232 | lightUntil((seqEncVal/4)%8,seqEncVal/32); 233 | seqLengths[gateOutNumber] = seqEncVal/4; 234 | }else{ 235 | if(seqEncVal > 12) seqEncVal = 12; 236 | trigSet = seqEncVal/4; 237 | menuSelect = true; 238 | menuTimeStp = millis(); 239 | lightsOut(); 240 | lightPattern(trigSet); 241 | } 242 | seqLastEncoded = seqEncoded; //store this value for next time 243 | } 244 | void MCP4922_write(int cs_pin, byte dac, int value) { 245 | byte low = value & 0xff; 246 | byte high = (value >> 8) & 0x0f; 247 | dac = (dac & 1) << 7; 248 | digitalWrite(cs_pin, LOW); 249 | SPI.transfer(dac | 0x30 | high); 250 | SPI.transfer(low); 251 | digitalWrite(cs_pin, HIGH); 252 | } 253 | 254 | static void scan(){ 255 | static uint8_t current = 0; 256 | uint8_t val; 257 | uint8_t i, j; 258 | 259 | // Select current columns 260 | digitalWrite(btncolumnpins[current], LOW); 261 | digitalWrite(ledcolumnpins[current], LOW); 262 | 263 | // output LED row values 264 | for (i = 0; i < NUM_LED_ROWS; i++){ 265 | if (LED_buffer[current][i]){ 266 | digitalWrite(ledRows[i], HIGH); 267 | } 268 | } 269 | delay(1); 270 | // Read the button inputs 271 | for ( j = 0; j < NUM_BTN_ROWS; j++){ 272 | val = digitalRead(btnrowpins[j]); 273 | if (val == LOW){ 274 | // active low: val is low when btn is pressed 275 | if ( debounce_count[current][j] < MAX_DEBOUNCE){ 276 | debounce_count[current][j]++; 277 | if ( debounce_count[current][j] == MAX_DEBOUNCE ){ 278 | Serial.println("btn Down: "); 279 | //mute column 280 | if(current == 0){ 281 | gateMutes[j] = !gateMutes[j]; 282 | gatesMutDwn[j] = true; 283 | clearPgTmStp[j] = millis(); 284 | anyMuteDown = true; 285 | }else{ 286 | //menu stuff 287 | if(menuOpen){ 288 | if(current == 1){ 289 | switch (j) { 290 | case 0: 291 | //copy 292 | for(int i=0; i<32; i++){ 293 | cpyTrigs[0][i][0] = trigs[trigSet][i][gateOutNumber]; 294 | cpyCvVals[0][i][0] = cvVals[trigSet][i][gateOutNumber]; 295 | } 296 | btnAnim = 1; 297 | btnAnimTmStp = millis(); 298 | break; 299 | case 1: 300 | //paste 301 | for(int i=0; i<32; i++){ 302 | trigs[trigSet][i][gateOutNumber] = cpyTrigs[0][i][0]; 303 | cvVals[trigSet][i][gateOutNumber] = cpyCvVals[0][i][0]; 304 | } 305 | btnAnim = 2; 306 | btnAnimTmStp = millis(); 307 | break; 308 | case 3: 309 | //save 310 | savePreset(); 311 | btnAnim = 3; 312 | btnAnimTmStp = millis(); 313 | break; 314 | } 315 | }else if (current == 2){ 316 | recAutomation = !recAutomation; 317 | recAutomation ? btnAnim = 4 : btnAnim = 0; 318 | }else if(current == 3){ 319 | speedIndex[j] = 0; 320 | }else if(current == 4){ 321 | speedIndex[j] = 1; 322 | }else if(current == 5){ 323 | speedIndex[j] = 2; 324 | }else if(current == 6){ 325 | speedIndex[j] = 3; 326 | }else if(current == 8){ 327 | randomizedRow[j] = !randomizedRow[j]; 328 | } 329 | }else{ 330 | //normal step edit 331 | LED_buffer[current][j] = !LED_buffer[current][j]; 332 | trigs[trigSet][(current-1)+seqPageMath[j]][gateOutNumber] = !trigs[trigSet][(current-1)+seqPageMath[j]][gateOutNumber]; 333 | noteDown = true; 334 | if(trigs[trigSet][(current-1)+seqPageMath[j]][gateOutNumber]){ 335 | cvStep = (current-1)+seqPageMath[j]; 336 | digitalWrite(gatePins[gateOutNumber], HIGH); 337 | } 338 | } 339 | } 340 | } 341 | } 342 | }else{ 343 | if ( debounce_count[current][j] > 0){ 344 | debounce_count[current][j]--; 345 | if ( debounce_count[current][j] == 0 ){ 346 | // If you want to do something when a key is released, do it here: 347 | if(current == 0){ 348 | gatesMutDwn[j] = false; 349 | anyMuteDown = false; 350 | }else{ 351 | noteDown = false; 352 | digitalWrite(gatePins[gateOutNumber], LOW); 353 | } 354 | } 355 | } 356 | } 357 | } 358 | delay(1); 359 | digitalWrite(btncolumnpins[current], HIGH); 360 | digitalWrite(ledcolumnpins[current], HIGH); 361 | 362 | for (i = 0; i < NUM_LED_ROWS; i++){ 363 | digitalWrite(ledRows[i], LOW); 364 | } 365 | current++; 366 | if (current >= NUM_LED_COLUMNS){ 367 | current = 0; 368 | } 369 | } 370 | 371 | void loop() { 372 | //MIDI CLOCK 373 | usbMIDI.read(); 374 | //Enoder Btns + Func Btn 375 | for(int i=0; i<3; i++){ 376 | extBtnSt[i] = analogRead(extBtnPins[i]); 377 | if(abs(extBtnSt[i] - extBtnStPrev[i]) > 100){ 378 | if(extBtnSt[i] < 2){ 379 | // Serial.print("btnDown: "); 380 | // Serial.println(i); 381 | if(i == 0){ 382 | tempBtnDown = true; 383 | initTmStp = millis(); 384 | internalClock = !internalClock; 385 | if(!internalClock){ 386 | gateSentTime = millis() - 3000; 387 | } 388 | }else if (i==1){ 389 | if(seqLengthMode){ 390 | lightsOut(); 391 | seqLengthMode = false; 392 | menuSelect = false; 393 | }else{ 394 | gateBtnDown = true; 395 | gateBtnTmStp = millis(); 396 | gateOutNumber++; 397 | if(gateOutNumber > 3){ 398 | gateOutNumber = 0; 399 | } 400 | lightsOut(); 401 | menuSelect = true; 402 | menuTimeStp = millis(); 403 | lightRow(gateOutNumber); 404 | } 405 | }else if(i==2){ 406 | menuOpen = true; 407 | lightsOut(); 408 | } 409 | }else{ 410 | if(i==0){ 411 | tempBtnDown = false; 412 | }else if(i==1){ 413 | gateBtnDown = false; 414 | }else if(i==2){ 415 | menuOpen = false; 416 | btnAnim = 0; 417 | recAutomation = false; 418 | } 419 | } 420 | extBtnStPrev[i] = extBtnSt[i]; 421 | } 422 | } 423 | //Reset Everything 424 | if(tempBtnDown && (millis() - initTmStp) > 1000){ 425 | initAll(); 426 | } 427 | //Reset Current Page 428 | for(int i=0; i<4; i++){ 429 | if(gatesMutDwn[i] && (millis() - clearPgTmStp[i]) > 3000){ 430 | initPage(i); 431 | } 432 | } 433 | //Seq Length Mode 434 | if(gateBtnDown && (millis() - gateBtnTmStp) > 300 && !seqLengthMode){ 435 | seqLengthMode = true; 436 | gateOutNumber--; 437 | if(gateOutNumber < 0){ 438 | gateOutNumber = 3; 439 | } 440 | seqEncVal = seqLengths[gateOutNumber]*4; 441 | seqLastEncoded = seqEncVal; 442 | lightsOut(); 443 | lightUntil((seqLengths[gateOutNumber])%8,seqLengths[gateOutNumber]/8); 444 | gateBtnTmStp = millis(); 445 | } 446 | //CV into trigset 447 | trigSetInput = (analogRead(seqSelPin)-350)/62; 448 | trigSetInput = constrain(trigSetInput, 0, 3); 449 | if(abs(trigSetInput - prevTrigSetInput) > 0){ 450 | //Serial.print("CV Pattern Set Change: ");Serial.println(trigSetInput); 451 | trigSet = trigSetInput; 452 | menuSelect = true; 453 | menuTimeStp = millis(); 454 | lightsOut(); 455 | lightPattern(trigSet); 456 | prevTrigSetInput = trigSetInput; 457 | } 458 | //ALl Btns 459 | scan(); 460 | //CV Knob 461 | analogValue = analogRead(analogPin); 462 | if(abs(analogValue - analogValueLag) > 1){ 463 | if(seqRunning && recAutomation){ 464 | cvVals[trigSet][gateSteps[gateOutNumber]][gateOutNumber] = analogValue; 465 | knobtoDac(); 466 | }else if(noteDown){ 467 | cvVals[trigSet][cvStep][gateOutNumber] = analogValue; 468 | knobtoDac(); 469 | } 470 | analogValueLag = analogValue; 471 | } 472 | 473 | 474 | 475 | //Internal Metro 476 | if(internalClock){ 477 | if(millis() - prevMetroTime > intervalTime){ 478 | seqStep++; 479 | for(int i=0; i<4; i++){ 480 | if(seqStep % seqSpeeds[speedIndex[i]] == 0){ 481 | if(randomizedRow[i]){ 482 | gateSteps[i] = random(0, seqLengths[i]); 483 | }else{ 484 | gateSteps[i]++; 485 | } 486 | } 487 | } 488 | seqRunning = true; 489 | prevMetroTime = millis(); 490 | } 491 | } 492 | 493 | //Sequencer 494 | if(abs(seqStep - prevSeqStep) > 0 && seqRunning){ 495 | allGatesOff = true; 496 | if(seqStep > 31) seqStep = 0; 497 | 498 | for(int i=0; i<4; i++){ 499 | if(gateSteps[i] > seqLengths[i]) gateSteps[i] = 0; 500 | } 501 | 502 | if(!menuSelect && !seqLengthMode && !menuOpen){ 503 | lightsOut(); 504 | lightActiveSteps(); 505 | for(int i=0; i<4; i++){ 506 | if(i==gateOutNumber){ 507 | lightSingle(gateSteps[i]%8,gateSteps[i]/8); 508 | } 509 | } 510 | } 511 | //turn gates off if on 512 | for(int i=0; i<4; i++){ 513 | if(seqStep % seqSpeeds[speedIndex[i]] == 0){ 514 | digitalWriteFast(gatePins[i], LOW); 515 | } 516 | } 517 | delay(1); 518 | //gate outs 519 | for(int i=0; i<4; i++){ 520 | if(trigs[trigSet][gateSteps[i]][i] && !gateMutes[i]){ 521 | digitalWriteFast(gatePins[i], HIGH); 522 | } 523 | } 524 | //cv outs 525 | if(cvVals[trigSet][gateSteps[0]][0] > 0 && !gateMutes[0]){ 526 | MCP4922_write(chip_pin_two, 1, cvVals[trigSet][gateSteps[0]][0]*4); 527 | } 528 | if(cvVals[trigSet][gateSteps[1]][1] > 0 && !gateMutes[1]){ 529 | MCP4922_write(chip_pin_one, 1, cvVals[trigSet][gateSteps[1]][1]*4); 530 | } 531 | if(cvVals[trigSet][gateSteps[2]][2] > 0 && !gateMutes[2]){ 532 | MCP4922_write(chip_pin_one, 0, cvVals[trigSet][gateSteps[2]][2]*4); 533 | } 534 | if(cvVals[trigSet][gateSteps[3]][3] > 0 && !gateMutes[3]){ 535 | MCP4922_write(chip_pin_two, 0, cvVals[trigSet][gateSteps[3]][3]*4); 536 | } 537 | 538 | gateSentTime = millis(); 539 | extrGtSntTm = gateSentTime; 540 | prevSeqStep = seqStep; 541 | } 542 | 543 | //LED Stuff 544 | if(menuOpen){ 545 | if(btnAnim !=0){ 546 | if(millis() > blkTmrM+100){ 547 | switch (btnAnim) { 548 | case 1: 549 | LED_buffer[1][0] = !LED_buffer[1][0]; 550 | break; 551 | case 2: 552 | LED_buffer[1][1] = !LED_buffer[1][1]; 553 | break; 554 | case 3: 555 | LED_buffer[1][3] = !LED_buffer[1][3]; 556 | break; 557 | case 4: 558 | LED_buffer[2][0] = !LED_buffer[2][0]; 559 | break; 560 | } 561 | blkTmrM = millis(); 562 | } 563 | if(millis() > btnAnimTmStp + 500 && btnAnim != 4){ 564 | btnAnim = 0; 565 | } 566 | }else{ 567 | LED_buffer[1][0] = true; 568 | LED_buffer[1][1] = true; 569 | LED_buffer[1][3] = true; 570 | //LED_buffer[2][0] = recAutomation; 571 | for(int r=0; r<4; r++){ 572 | randomizedRow[r] ? LED_buffer[8][r] = true : LED_buffer[8][r] = false; 573 | for(int c=0; c<4; c++){ 574 | if(speedIndex[c] >= r){ 575 | LED_buffer[r+3][c] = true; 576 | }else{ 577 | LED_buffer[r+3][c] = false; 578 | } 579 | } 580 | } 581 | } 582 | } 583 | //reset seq 584 | if(millis() > gateSentTime + 3000 && !menuSelect && !seqLengthMode && !menuOpen){ 585 | lightsOut(); 586 | resetSeq(); 587 | lightActiveSteps(); 588 | extrGtSntTm = 0; 589 | } 590 | if(millis() > menuTimeStp + 300){ 591 | menuSelect = false; 592 | } 593 | //Mute Leds 594 | for(int i=0; i<4; i++){ 595 | if(!gateMutes[i] && i != gateOutNumber){ 596 | LED_buffer[0][i] = true; 597 | }else if(!gateMutes[i] && gateOutNumber == i){ 598 | if(millis() > blkTmr+200){ 599 | LED_buffer[0][i] = !LED_buffer[0][i]; 600 | blkTmr = millis(); 601 | } 602 | }else if(gateMutes[i] && i == gateOutNumber){ 603 | if(millis() > blkTmrM+100){ 604 | LED_buffer[0][i] = !LED_buffer[0][i]; 605 | blkTmrM = millis(); 606 | } 607 | }else{ 608 | LED_buffer[0][i] = false; 609 | } 610 | } 611 | } 612 | void knobtoDac(){ 613 | switch (gateOutNumber) { 614 | case 0: 615 | MCP4922_write(chip_pin_two, 1, analogValue*4); 616 | break; 617 | case 1: 618 | MCP4922_write(chip_pin_one, 1, analogValue*4); 619 | break; 620 | case 2: 621 | MCP4922_write(chip_pin_one, 0, analogValue*4); 622 | break; 623 | case 3: 624 | MCP4922_write(chip_pin_two, 0, analogValue*4); 625 | break; 626 | } 627 | } 628 | void savePreset(){ 629 | int trigSpot = 0; 630 | int cvSpot = 512; 631 | int lengthSpot = 1025; 632 | int randomizeSpot = 1029; 633 | int speedSpot = 1033; 634 | for(int i=0; i<4; i++){ 635 | EEPROM.write(i+lengthSpot, seqLengths[i]); 636 | EEPROM.write(i+randomizeSpot, randomizedRow[i]); 637 | EEPROM.write(i+speedSpot, speedIndex[i]); 638 | for(int j=0; j<32; j++){ 639 | for(int s=0; s<4; s++){ 640 | EEPROM.write(trigSpot, trigs[i][j][s]); 641 | EEPROM.write(cvSpot, cvVals[i][j][s] / 4); 642 | trigSpot++; 643 | cvSpot++; 644 | } 645 | } 646 | } 647 | EEPROM.write(1037, tempEncVal/4); 648 | Serial.println("done saving"); 649 | } 650 | void loadPreset(){ 651 | int trigSpot = 0; 652 | int cvSpot = 512; 653 | int lengthSpot = 1025; 654 | int randomizeSpot = 1029; 655 | int speedSpot = 1033; 656 | for(int i=0; i<4; i++){ 657 | seqLengths[i] = EEPROM.read(i+lengthSpot); 658 | randomizedRow[i] = EEPROM.read(i+randomizeSpot); 659 | speedIndex[i] = EEPROM.read(i+speedSpot); 660 | for(int j=0; j<32; j++){ 661 | for(int s=0; s<4; s++){ 662 | trigs[i][j][s] = EEPROM.read(trigSpot); 663 | cvVals[i][j][s] = EEPROM.read(cvSpot) * 4; 664 | Serial.println(cvVals[i][j][s]); 665 | trigSpot++; 666 | cvSpot++; 667 | } 668 | } 669 | } 670 | tempEncVal = EEPROM.read(1037) * 4; 671 | if(tempEncVal > 1000) tempEncVal = 1000; 672 | intervalTime = (1000 - tempEncVal) + 20; 673 | tempLastEncoded = tempEncoded; 674 | Serial.println("done loading"); 675 | } 676 | void resetSeq(){ 677 | seqStep = 31; 678 | for(int i=0; i<4; i++){ 679 | gateSteps[i] = 31; 680 | if(allGatesOff){ 681 | digitalWriteFast(gatePins[i], LOW); 682 | } 683 | } 684 | allGatesOff = false; 685 | prevSeqStep = 1; 686 | seqRunning = false; 687 | internalClock = false; 688 | } 689 | void initAll(){ 690 | Serial.println("clear everything"); 691 | lightsOut(); 692 | lightAll(); 693 | for(int i=0; i<4; i++){ 694 | gateMutes[i] = false; 695 | seqLengths[i] = 31; 696 | randomizedRow[i] = false; 697 | for(int j=0; j<32; j++){ 698 | for(int s=0; s<4; s++){ 699 | trigs[i][j][s] = false; 700 | cvVals[i][j][s] = 0; 701 | } 702 | } 703 | } 704 | seqEncVal = 0; 705 | seqLastEncoded = seqEncVal; 706 | gateOutNumber = 0; 707 | resetSeq(); 708 | gateSentTime = millis() - 3000; 709 | } 710 | void initPage(int gateNumber){ 711 | Serial.println("clear page"); 712 | lightsOut(); 713 | lightAll(); 714 | for(int j=0; j<32; j++){ 715 | for(int s=0; s<4; s++){ 716 | trigs[trigSet][j][gateNumber] = false; 717 | cvVals[trigSet][j][gateNumber] = 0; 718 | } 719 | } 720 | gateMutes[gateNumber] = false; 721 | } 722 | 723 | void lightPattern(int column){ 724 | for(int i=0; i 0){ 745 | LED_buffer[j][i] = false; 746 | } 747 | } 748 | } 749 | } 750 | void lightAll(){ 751 | menuSelect = true; 752 | menuTimeStp = millis(); 753 | for (int i = 0; i < NUM_LED_ROWS; i++){ 754 | for(int j=0; j 0){ 763 | LED_buffer[j][i] = true; 764 | } 765 | } 766 | } 767 | } 768 | void lightUntil(int col, int row){ 769 | for(int i=0; i<8; i++){ 770 | if(i <= col%8){ 771 | LED_buffer[i+1][row] = true; 772 | }else{ 773 | LED_buffer[i+1][row] = false; 774 | } 775 | } 776 | if(row == 1){ 777 | lightRow(0); 778 | }else if(row == 2){ 779 | lightRow(0); 780 | lightRow(1); 781 | }else if(row == 3){ 782 | lightRow(0); 783 | lightRow(1); 784 | lightRow(2); 785 | } 786 | } 787 | //MIDI CLOCK 788 | void RealTimeSystem(byte realtimebyte) { 789 | if(realtimebyte == START || realtimebyte == CONTINUE) { 790 | counter = 0; 791 | seqRunning = false; 792 | resetSeq(); 793 | } 794 | 795 | if(realtimebyte == 248) { 796 | counter++; 797 | if(counter == 6) { 798 | counter = 0; 799 | } 800 | if(counter == 1){ 801 | internalClock = false; 802 | intervalTime = millis() - extrGtSntTm; 803 | seqRunning = true; 804 | seqStep++; 805 | for(int i=0; i<4; i++){ 806 | if(seqStep % seqSpeeds[speedIndex[i]] == 0){ 807 | if(randomizedRow[i]){ 808 | gateSteps[i] = random(0, seqLengths[i]); 809 | }else{ 810 | gateSteps[i]++; 811 | } 812 | } 813 | } 814 | } 815 | } 816 | if(realtimebyte == STOP) { 817 | resetSeq(); 818 | } 819 | } 820 | -------------------------------------------------------------------------------- /Nimbus/Nimbus.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // GUItool: begin automatically generated code 8 | AudioSynthWaveform voiceOneB; //xy=387.5,590 9 | AudioSynthWaveform voiceTwoB; //xy=387.5,624 10 | AudioSynthWaveform voiceTwoD; //xy=389.5,1045 11 | AudioSynthWaveform voiceOneD; //xy=390.5,1009 12 | AudioSynthWaveform voiceThreeB; //xy=392.5,660 13 | AudioSynthNoiseWhite noiseVoiceB; //xy=393.5,694 14 | AudioSynthWaveform voiceThreeD; //xy=392.5,1080 15 | AudioSynthNoiseWhite noiseVoiceD; //xy=392.5,1114 16 | AudioSynthWaveform voiceTwoC; //xy=410.5,845 17 | AudioSynthWaveform voiceOneC; //xy=411.5,810 18 | AudioSynthNoiseWhite noiseVoiceC; //xy=411.5,917 19 | AudioSynthWaveform voiceThreeC; //xy=414.5,881 20 | AudioSynthWaveform voiceOneA; //xy=454.5,300 21 | AudioSynthWaveform voiceTwoA; //xy=454.5,336 22 | AudioSynthNoiseWhite noiseVoiceA; //xy=455.5,411 23 | AudioSynthWaveform voiceThreeA; //xy=458.5,373 24 | AudioMixer4 voiceMixerB; //xy=567.5,655 25 | AudioSynthWaveformDc envelopeB; //xy=577.5,600 26 | AudioSynthWaveformDc envelopeC; //xy=578.5,817 27 | AudioMixer4 voiceMixerC; //xy=578.5,877 28 | AudioMixer4 voiceMixerD; //xy=579.5,1070 29 | AudioSynthWaveformDc envelopeD; //xy=588.5,1006 30 | AudioMixer4 voiceMixerA; //xy=635.5,364 31 | AudioSynthWaveformDc envelopeA; //xy=639.5,306 32 | AudioEffectMultiply multiplyB; //xy=726.5,627 33 | AudioEffectMultiply multiplyC; //xy=738.5,848 34 | AudioEffectMultiply multiplyD; //xy=738.5,1035 35 | AudioSynthWaveform LFO1; //xy=757.5,770 36 | AudioEffectMultiply multiplyA; //xy=796.5,354 37 | AudioSynthWaveformDc filterEnvD; //xy=819.5,1113 38 | AudioSynthWaveformDc filterEnvB; //xy=849.5,675 39 | AudioSynthWaveformDc filterEnvA; //xy=854.5,445 40 | AudioSynthWaveformDc filterEnvC; //xy=860.5,892 41 | AudioMixer4 filterModMixerD; //xy=977.5,1176 42 | AudioMixer4 filterModMixerB; //xy=1002.5,727 43 | AudioMixer4 filterModMixerA; //xy=1007.5,475 44 | AudioMixer4 filterModMixerC; //xy=1012.5,950 45 | AudioSynthWaveformDc lfo2Amt; //xy=1050.5,185 46 | AudioSynthWaveformSine LFO2; //xy=1050.5,232 47 | AudioFilterStateVariable filterA; //xy=1172.5,434 48 | AudioFilterStateVariable filterD; //xy=1175.5,1097 49 | AudioFilterStateVariable filterB; //xy=1183.5,673 50 | AudioAnalyzePeak peakC; //xy=1183.5,775 51 | AudioFilterStateVariable filterC; //xy=1183.5,865 52 | AudioAnalyzePeak peakD; //xy=1183.5,1011 53 | AudioAnalyzePeak peakA; //xy=1187.5,365 54 | AudioAnalyzePeak peakB; //xy=1205.5,557 55 | AudioMixer4 LfoMixer; //xy=1207.5,235 56 | AudioAnalyzePeak lfoPeak; //xy=1364.5,229 57 | AudioMixer4 finalMixer; //xy=1388.5,692 58 | AudioAnalyzePeak finalPeak; //xy=1586.5,779 59 | AudioOutputI2S i2s1; //xy=1592.5,691 60 | AudioConnection patchCord1(voiceOneB, 0, voiceMixerB, 0); 61 | AudioConnection patchCord2(voiceTwoB, 0, voiceMixerB, 1); 62 | AudioConnection patchCord3(voiceTwoD, 0, voiceMixerD, 1); 63 | AudioConnection patchCord4(voiceOneD, 0, voiceMixerD, 0); 64 | AudioConnection patchCord5(voiceThreeB, 0, voiceMixerB, 2); 65 | AudioConnection patchCord6(noiseVoiceB, 0, voiceMixerB, 3); 66 | AudioConnection patchCord7(voiceThreeD, 0, voiceMixerD, 2); 67 | AudioConnection patchCord8(noiseVoiceD, 0, voiceMixerD, 3); 68 | AudioConnection patchCord9(voiceTwoC, 0, voiceMixerC, 1); 69 | AudioConnection patchCord10(voiceOneC, 0, voiceMixerC, 0); 70 | AudioConnection patchCord11(noiseVoiceC, 0, voiceMixerC, 3); 71 | AudioConnection patchCord12(voiceThreeC, 0, voiceMixerC, 2); 72 | AudioConnection patchCord13(voiceOneA, 0, voiceMixerA, 0); 73 | AudioConnection patchCord14(voiceTwoA, 0, voiceMixerA, 1); 74 | AudioConnection patchCord15(noiseVoiceA, 0, voiceMixerA, 3); 75 | AudioConnection patchCord16(voiceThreeA, 0, voiceMixerA, 2); 76 | AudioConnection patchCord17(voiceMixerB, 0, multiplyB, 1); 77 | AudioConnection patchCord18(envelopeB, 0, multiplyB, 0); 78 | AudioConnection patchCord19(envelopeC, 0, multiplyC, 0); 79 | AudioConnection patchCord20(voiceMixerC, 0, multiplyC, 1); 80 | AudioConnection patchCord21(voiceMixerD, 0, multiplyD, 1); 81 | AudioConnection patchCord22(envelopeD, 0, multiplyD, 0); 82 | AudioConnection patchCord23(voiceMixerA, 0, multiplyA, 1); 83 | AudioConnection patchCord24(envelopeA, 0, multiplyA, 0); 84 | AudioConnection patchCord25(multiplyB, 0, filterB, 0); 85 | AudioConnection patchCord26(multiplyC, 0, filterC, 0); 86 | AudioConnection patchCord27(multiplyD, 0, filterD, 0); 87 | AudioConnection patchCord28(LFO1, 0, filterModMixerA, 1); 88 | AudioConnection patchCord29(LFO1, 0, filterModMixerB, 1); 89 | AudioConnection patchCord30(LFO1, 0, filterModMixerC, 1); 90 | AudioConnection patchCord31(LFO1, 0, filterModMixerD, 1); 91 | AudioConnection patchCord32(multiplyA, 0, filterA, 0); 92 | AudioConnection patchCord33(filterEnvD, 0, filterModMixerD, 0); 93 | AudioConnection patchCord34(filterEnvB, 0, filterModMixerB, 0); 94 | AudioConnection patchCord35(filterEnvA, 0, filterModMixerA, 0); 95 | AudioConnection patchCord36(filterEnvC, 0, filterModMixerC, 0); 96 | AudioConnection patchCord37(filterModMixerD, 0, filterD, 1); 97 | AudioConnection patchCord38(filterModMixerB, 0, filterB, 1); 98 | AudioConnection patchCord39(filterModMixerA, 0, filterA, 1); 99 | AudioConnection patchCord40(filterModMixerC, 0, filterC, 1); 100 | AudioConnection patchCord41(lfo2Amt, 0, LfoMixer, 0); 101 | AudioConnection patchCord42(LFO2, 0, LfoMixer, 1); 102 | AudioConnection patchCord43(filterA, 0, finalMixer, 0); 103 | AudioConnection patchCord44(filterA, 0, peakA, 0); 104 | AudioConnection patchCord45(filterD, 0, finalMixer, 3); 105 | AudioConnection patchCord46(filterD, 0, peakD, 0); 106 | AudioConnection patchCord47(filterB, 0, finalMixer, 1); 107 | AudioConnection patchCord48(filterB, 0, peakB, 0); 108 | AudioConnection patchCord49(filterC, 0, finalMixer, 2); 109 | AudioConnection patchCord50(filterC, 0, peakC, 0); 110 | AudioConnection patchCord51(LfoMixer, lfoPeak); 111 | AudioConnection patchCord52(finalMixer, 0, i2s1, 0); 112 | AudioConnection patchCord53(finalMixer, 0, i2s1, 1); 113 | AudioConnection patchCord54(finalMixer, finalPeak); 114 | AudioControlSGTL5000 sgtl5000_1; //xy=1371.5,273 115 | // GUItool: end automatically generated code 116 | 117 | 118 | 119 | 120 | 121 | /////////////////////////////////////////////////////////////////////////////////////// 122 | //======================================PINS=========================================// 123 | 124 | //======Teensy 125 | 126 | // 0 = Touch 1 127 | // 1 = Touch 2 128 | // 2 = Neos 129 | // 3 = Osc One Shape 130 | // 4 = Osc Two Shape 131 | // 5 = Osc Three Shape 132 | // 6 = AUDIO BOARD 133 | // 7 = AUDIO BOARD 134 | // 8 = LFO Shape 135 | // 9 = AUDIO BOARD 136 | // 10 = AUDIO BOARD 137 | // 11 = AUDIO BOARD 138 | // 12 = AUDIO BOARD 139 | 140 | // 13 = AUDIO BOARD 141 | // 14 = AUDIO BOARD 142 | // 15 = Touch 3 143 | // 16 = Touch 4 144 | // 17 = Touch 5 145 | // 18 = AUDIO BOARD 146 | // 19 = AUDIO BOARD 147 | // 20 = Encoder Btn 148 | // 21 = Encoder Pin 1 149 | // 22 = AUDIO BOARD 150 | // 23 = AUDIO BOARD 151 | // 24 = Encoder Pin 2 152 | // 25 = Touch 6 153 | // 26 = S0 - MUX 154 | // 27 = S1 - MUX 155 | // 28 = S2 - MUX 156 | // 29 = S3 - MUX 157 | // 30 = SIG - MUX 158 | // 32 = Touch 7 159 | // 33 = Touch 8 160 | 161 | //======Mux 162 | 163 | // 0 = Osc One Vol 164 | // 1 = Osc Two Vol 165 | // 2 = Osc Three Vol 166 | // 3 = Noise Vol 167 | // 4 = LFO2 Freq 168 | // 5 = LFO2 Amount 169 | // 6 = Detune 170 | // 7 = LFO1 Freq 171 | // 8 = LFO1 Amt 172 | // 9 = Amp Env Attack 173 | // 10 = Amp Env Release 174 | // 11 = Filter Env Attack 175 | // 12 = Filter Env Release 176 | // 13 = Filter Freq 177 | // 14 = Filter Res 178 | // 15 = Octave 179 | 180 | /////////////////////////////////////////////////////////////////////////////////////// 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | #include 192 | #include 193 | #include 194 | 195 | //Pixels 196 | #define PIXEL_PIN 2 197 | #define NUMPIXELS 12 198 | Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXEL_PIN, NEO_GRB + NEO_KHZ800); 199 | 200 | //Encoder 201 | int encoderPin1 = 21; 202 | int encoderPin2 = 24; 203 | volatile int lastEncoded = 0; 204 | volatile long encoderValue = 0; 205 | int scaledEncVal; 206 | int prevScaledEncVal; 207 | 208 | //Touch Pins 209 | bool noteTouched[8]; 210 | int noteTouchPins[8] = {0,1,15,16,17,25,32,33}; 211 | float noteCurrent[8]; 212 | 213 | //Switches/EncoderBtn 214 | Bounce btnSwBouncers[5] = { 215 | Bounce(3,10), 216 | Bounce(4,10), 217 | Bounce(5,10), 218 | Bounce(8,10), 219 | Bounce(20,10), 220 | }; 221 | int btnSwPins[5] = {3,4,5,8,20}; 222 | 223 | //Mux control pins 224 | int s0 = 26; 225 | int s1 = 27; 226 | int s2 = 28; 227 | int s3 = 29; 228 | //Mux in "SIG" pin 229 | int SIG_pin = 30; 230 | 231 | //Knobs 232 | float analogValues[16]; 233 | float analogValuesLag[16]; 234 | 235 | 236 | //FirstRunFlag 237 | bool firstRun; 238 | 239 | int menuCount; 240 | int encoded; 241 | unsigned long clearTimeStamp; 242 | 243 | //preset stuff 244 | const int chipSelect = 10; 245 | int presetNumber = -1; 246 | File myFile; 247 | String fileNames[8] = {"1.txt","2.txt","3.txt","4.txt","5.txt","6.txt","7.txt","8.txt"}; 248 | bool paramLocks[16]; 249 | 250 | //sequencer 251 | Metro metronome = Metro(500); 252 | bool seqRunning; 253 | int metroInterval = 300; 254 | int seqStep; 255 | int prevSeqStep; 256 | int seqPage; 257 | bool seqEditMode; 258 | float seqFrequencies[4][8]; 259 | float seqFrequenciesTwo[4][8]; 260 | bool seqStepClearFlag; 261 | unsigned long seqStepClearTimeStamp; 262 | //float seqVelocities[4][8]; 263 | float currentSeqNote; 264 | float currentSeqNoteTwo; 265 | int seqLength; 266 | 267 | 268 | 269 | //Synth Params 270 | 271 | float rawVals[20]; 272 | 273 | float finalAmp; 274 | float voiceAPeak; 275 | float voiceBPeak; 276 | float voiceCPeak; 277 | float voiceDPeak; 278 | 279 | int scale; 280 | float noteFrequencies[8][8] = { 281 | //Amin 282 | {220.00,246.94,261.63,293.66,329.63,349.23,392.00,440.00}, 283 | //Bmin 284 | {246.94,277.18,293.66,329.63,369.99,392.00,440.00,493.88}, 285 | //Cmin 286 | {261.63,293.66,311.13,349.23,392.00,415.30,466.16,523.25}, 287 | //Dmin 288 | {293.66,329.63,349.23,392.00,440.00,466.16,523.25,587.33}, 289 | //Emin 290 | {329.63,369.99,392.00,440.00,493.88,523.25,587.33,659.25}, 291 | //Fmin 292 | {349.23,392.00,415.30,466.16,523.25,554.37,622.25,698.46}, 293 | //Gmin 294 | {392.00,440.00,466.16,523.25,587.33,622.25,698.46,783.99}, 295 | //Chrom 296 | {220.00,233.08,246.94,261.63,277.18,293.66,311.13,329.63}, 297 | }; 298 | int noteMIDINumbers[8][8] = { 299 | //Amin 300 | {57,59,60,62,64,65,67,69}, 301 | //Bmin 302 | {59,61,62,64,66,67,69,71}, 303 | //Cmin 304 | {60,62,63,65,67,68,70,72}, 305 | //Dmin 306 | {62,64,65,67,69,70,72,74}, 307 | //Emin 308 | {64,66,67,69,71,72,74,76}, 309 | //Fmin 310 | {65,67,68,70,72,73,75,77}, 311 | //Gmin 312 | {67,69,70,72,74,75,77,79}, 313 | //Chrom 314 | {57,58,59,60,61,62,63,64}, 315 | }; 316 | 317 | float frequency; 318 | 319 | int attackTime = 10; 320 | int releaseTime = 10; 321 | float lfoAmt; 322 | float lfoFreq; 323 | int lfoTimeMathArray[5] = {250, 500, 1000, 2000, 4000}; 324 | int lfoIndex; 325 | float seqInterval; 326 | float lfoTwoAmt; 327 | float lfoTwoFreq; 328 | float lfoPitchMod; 329 | float octave[4] = {.25,.5,1,2}; 330 | int midiOctave[4] = {-24, -12, 0, 12}; 331 | int octaveKey; 332 | int filterFreq; 333 | float filterRes; 334 | float masterDetune; 335 | float plusDetune; 336 | float minusDetune; 337 | unsigned long filterEnvAttack; 338 | unsigned long filterEnvRelease; 339 | 340 | float voices[4]; 341 | float VoiceFreq[4]; 342 | float VoiceVel[4]; 343 | float voiceMod; 344 | 345 | float ampArray[4]; 346 | int voiceNum; 347 | //float currentVel; 348 | 349 | uint32_t indicatorColor[2] = { 350 | pixels.Color(255,255,0), 351 | pixels.Color(255,0,0) 352 | }; 353 | int indicatorIndex; 354 | 355 | 356 | 357 | 358 | void setup() { 359 | 360 | AudioMemory(64); 361 | sgtl5000_1.enable(); 362 | sgtl5000_1.volume(.8); 363 | 364 | Serial.begin(9600); 365 | 366 | //MIDI 367 | usbMIDI.setHandleNoteOff(OnNoteOff); 368 | usbMIDI.setHandleNoteOn(OnNoteOn); 369 | usbMIDI.setHandleControlChange(OnControlChange); 370 | 371 | //SD 372 | SPI.setMOSI(7); // Audio shield has MOSI on pin 7 373 | SPI.setSCK(14); // Audio shield has SCK on pin 14 374 | Serial.print("Initializing SD card..."); 375 | if (!SD.begin(chipSelect)) { 376 | Serial.println("initialization failed!"); 377 | return; 378 | } 379 | Serial.println("initialization done."); 380 | 381 | 382 | 383 | //lfoMixer 384 | LfoMixer.gain(0,.5); 385 | LfoMixer.gain(1,.5); 386 | 387 | lfo2Amt.amplitude(1); 388 | LFO2.amplitude(1); 389 | LFO2.frequency(1); 390 | 391 | //finalMixer 392 | finalMixer.gain(0,.25); 393 | finalMixer.gain(1,.25); 394 | finalMixer.gain(2,.25); 395 | finalMixer.gain(3,.25); 396 | 397 | //Voice 1 398 | voiceOneA.amplitude(.25); 399 | voiceOneB.amplitude(.25); 400 | voiceOneC.amplitude(.25); 401 | voiceOneD.amplitude(.25); 402 | //Voice 2 403 | voiceTwoA.amplitude(.25); 404 | voiceTwoB.amplitude(.25); 405 | voiceTwoC.amplitude(.25); 406 | voiceTwoD.amplitude(.25); 407 | //Voice 3 408 | voiceThreeA.amplitude(.25); 409 | voiceThreeB.amplitude(.25); 410 | voiceThreeC.amplitude(.25); 411 | voiceThreeD.amplitude(.25); 412 | //noise 413 | noiseVoiceA.amplitude(.125); 414 | noiseVoiceB.amplitude(.125); 415 | noiseVoiceC.amplitude(.125); 416 | noiseVoiceD.amplitude(.125); 417 | //LFO 418 | LFO1.begin(.7,.5,WAVEFORM_SAWTOOTH_REVERSE); 419 | 420 | //filter 421 | filterA.octaveControl(2.5); 422 | filterB.octaveControl(2.5); 423 | filterC.octaveControl(2.5); 424 | filterD.octaveControl(2.5); 425 | 426 | 427 | 428 | //ENCODER KNOB 429 | pinMode(encoderPin1, INPUT); 430 | pinMode(encoderPin2, INPUT); 431 | digitalWrite(encoderPin1, HIGH); 432 | digitalWrite(encoderPin2, HIGH); 433 | attachInterrupt(21, updateEncoder, CHANGE); 434 | attachInterrupt(24, updateEncoder, CHANGE); 435 | 436 | //Pixels 437 | pixels.begin(); 438 | pixels.setBrightness(200); 439 | 440 | 441 | //pixelDance 442 | for (int i = 0; i < NUMPIXELS; ++i){ 443 | pixels.setPixelColor(i, pixels.Color(0, 100, 255)); 444 | pixels.show(); 445 | delay(100); 446 | } 447 | 448 | //Switches/EncoderBtn 449 | pinMode(3, INPUT_PULLUP); 450 | pinMode(4, INPUT_PULLUP); 451 | pinMode(5, INPUT_PULLUP); 452 | pinMode(8, INPUT_PULLUP); 453 | pinMode(20, INPUT_PULLUP); 454 | 455 | //Mux 456 | pinMode(s0, OUTPUT); 457 | pinMode(s1, OUTPUT); 458 | pinMode(s2, OUTPUT); 459 | pinMode(s3, OUTPUT); 460 | pinMode(SIG_pin, INPUT); 461 | digitalWrite(s0, LOW); 462 | digitalWrite(s1, LOW); 463 | digitalWrite(s2, LOW); 464 | digitalWrite(s3, LOW); 465 | 466 | firstRun = true; 467 | 468 | } 469 | 470 | void loop(){ 471 | 472 | usbMIDI.read(); 473 | 474 | //VoicePixels 475 | if (seqEditMode || seqRunning){ 476 | pixels.setPixelColor(seqPage + 8,pixels.Color(0,0,255)); 477 | }else{ 478 | pixels.setPixelColor(8,pixels.Color(255*voiceAPeak,0,0)); 479 | pixels.setPixelColor(9,pixels.Color(0,255*voiceBPeak,0)); 480 | pixels.setPixelColor(10,pixels.Color(0,0,255*voiceCPeak)); 481 | pixels.setPixelColor(11,pixels.Color(255*voiceDPeak,255*voiceDPeak,0)); 482 | } 483 | 484 | //BtnPixels 485 | if (menuCount > 0){ 486 | //menu stuff 487 | switch (menuCount) { 488 | case 1: 489 | //Loading Presets 490 | for (int i = 0; i < 8; ++i){ 491 | pixels.setPixelColor(i, pixels.Color(0, 255, 0)); 492 | pixels.setPixelColor(presetNumber, pixels.Color(0, 0, 255)); 493 | } 494 | break; 495 | case 2: 496 | //Saving Presets 497 | for (int i = 0; i < 8; ++i){ 498 | pixels.setPixelColor(i, pixels.Color(255, 0, 0)); 499 | pixels.setPixelColor(presetNumber, pixels.Color(0, 0, 255)); 500 | } 501 | break; 502 | case 3: 503 | //scale 504 | pixels.setPixelColor(scale, pixels.Color(0, 0, 255)); 505 | break; 506 | } 507 | }else{ 508 | if (!seqRunning){ 509 | //Normal amp stuff 510 | for (int i = 0; i < 8; ++i){ 511 | pixels.setPixelColor(i, pixels.Color(0,0,255*finalAmp)); 512 | } 513 | } 514 | } 515 | pixels.show(); 516 | 517 | //Note Touches 518 | for (int i = 0; i < 8; ++i){ 519 | noteCurrent[i] = smoothRead(noteTouchPins[i]); 520 | 521 | if (noteCurrent[i] > 1000 && noteTouched[i] == false){ 522 | if (menuCount == 1){ 523 | presetNumber = i; 524 | loadPreset(i); 525 | }else if(menuCount == 2){ 526 | presetNumber = i; 527 | savePreset(i); 528 | }else if(menuCount == 3){ 529 | scale = i; 530 | }else if(menuCount == 4){ 531 | //enter seq steps 532 | 533 | 534 | if(seqFrequencies[seqPage][seqStep % 8] || seqFrequenciesTwo[seqPage][seqStep % 8]){ 535 | seqStepClearTimeStamp = millis(); 536 | seqStepClearFlag = true; 537 | } 538 | //store step * octave 539 | frequency = noteFrequencies[scale][i]; 540 | startVoice(frequency, 1); 541 | //mono or poly - 2 note max 542 | if (!seqFrequencies[seqPage][seqStep % 8]){ 543 | seqFrequencies[seqPage][seqStep % 8] = noteFrequencies[scale][i] * octave[octaveKey]; 544 | }else if(!seqFrequenciesTwo[seqPage][seqStep % 8]){ 545 | seqFrequenciesTwo[seqPage][seqStep % 8] = noteFrequencies[scale][i] * octave[octaveKey]; 546 | } 547 | 548 | }else{ 549 | //just play the note 550 | frequency = noteFrequencies[scale][i]; 551 | startVoice(frequency, 1); 552 | usbMIDI.sendNoteOn(noteMIDINumbers[scale][i] + midiOctave[octaveKey], 127, 1); 553 | } 554 | 555 | noteTouched[i] = true; 556 | 557 | }else if (noteCurrent[i] < 1000 && noteTouched[i] == true){ 558 | if (menuCount > 0 && menuCount < 4){ 559 | menuCount = 0; 560 | }else{ 561 | seqStepClearFlag = false; 562 | //End normal note 563 | frequency = noteFrequencies[scale][i]; 564 | endVoice(frequency); 565 | usbMIDI.sendNoteOff(noteMIDINumbers[scale][i] + midiOctave[octaveKey], 99, 1); 566 | } 567 | noteTouched[i] = false; 568 | } 569 | } 570 | 571 | //Sequencer Metro 572 | if (seqRunning){ 573 | if (metronome.check() == 1) { 574 | seqStep++; 575 | LFO1.phase(180); 576 | } 577 | } 578 | 579 | //Sequencer 580 | if (seqEditMode || seqRunning){ 581 | //One action Per Step 582 | if(abs(seqStep - prevSeqStep) > 0){ 583 | neoPixelsOff(); 584 | indicatorIndex = 0; 585 | 586 | if (seqRunning){ 587 | if (seqStep > (seqLength - 1)){ 588 | seqStep = 0; 589 | } 590 | }else{ 591 | if (seqStep > 31){ 592 | seqStep = 0; 593 | } 594 | } 595 | 596 | if (seqPage > 3){ 597 | seqPage = 0; 598 | } 599 | 600 | seqPage = seqStep/8; 601 | 602 | if (currentSeqNote > 0){ 603 | endVoice(currentSeqNote); 604 | } 605 | if (currentSeqNoteTwo > 0){ 606 | endVoice(currentSeqNoteTwo); 607 | } 608 | 609 | if(seqFrequencies[seqPage][seqStep % 8]){ 610 | startVoice(seqFrequencies[seqPage][seqStep % 8], 1); 611 | currentSeqNote = seqFrequencies[seqPage][seqStep % 8]; 612 | } 613 | if(seqFrequenciesTwo[seqPage][seqStep % 8]){ 614 | startVoice(seqFrequenciesTwo[seqPage][seqStep % 8], 1); 615 | currentSeqNoteTwo = seqFrequenciesTwo[seqPage][seqStep % 8]; 616 | } 617 | 618 | prevSeqStep = seqStep; 619 | } 620 | if (menuCount == 4 || menuCount == 0){ 621 | for (int i = 0; i < 8; ++i){ 622 | //background blue 623 | //pixels.setPixelColor(i, pixels.Color(0,0,20)); 624 | //Green/teal if there is a note(s) stored 625 | if (seqFrequencies[seqPage][i] && seqFrequenciesTwo[seqPage][i]){ 626 | pixels.setPixelColor(i, pixels.Color(100,255,0)); 627 | }else if (seqFrequencies[seqPage][i]){ 628 | pixels.setPixelColor(i, pixels.Color(0,255,0)); 629 | } 630 | //Indicate the step you are on 631 | pixels.setPixelColor(seqStep % 8, indicatorColor[indicatorIndex]); 632 | } 633 | } 634 | } 635 | 636 | //clearStep 637 | if(menuCount == 4 && seqStepClearFlag){ 638 | if (abs(millis() - seqStepClearTimeStamp) > 2000){ 639 | Serial.println("clearStep"); 640 | 641 | endVoice(seqFrequencies[seqPage][seqStep % 8]); 642 | seqFrequencies[seqPage][seqStep % 8] = 0; 643 | 644 | endVoice(seqFrequenciesTwo[seqPage][seqStep % 8]); 645 | seqFrequenciesTwo[seqPage][seqStep % 8] = 0; 646 | 647 | 648 | seqStepClearFlag = false; 649 | seqStepClearTimeStamp = millis(); 650 | indicatorIndex = 1; 651 | } 652 | } 653 | 654 | //Encoder 655 | if (abs(scaledEncVal - prevScaledEncVal) > 0){ 656 | if (seqEditMode){ 657 | seqStep = scaledEncVal; //Step Selection 658 | }else if (seqRunning){ 659 | seqInterval = 2000 - encoderValue; 660 | metronome.interval(seqInterval); //Speed 661 | lfoFreq = (1/seqInterval)*lfoTimeMathArray[lfoIndex]; 662 | } 663 | prevScaledEncVal = scaledEncVal; 664 | } 665 | 666 | //Knobs 667 | for (int i = 0; i < 16; ++i){ 668 | setMuxPin(i); 669 | analogValues[i] = analogRead(SIG_pin); 670 | 671 | if ((abs(analogValues[i] - analogValuesLag[i]) > 1) || firstRun){ 672 | 673 | if (paramLocks[i] && (abs(analogValues[i] - rawVals[i]) < 20)) { 674 | paramLocks[i] = false; 675 | } 676 | if (!paramLocks[i]){ 677 | 678 | rawVals[i] = analogValues[i]; 679 | 680 | setSynthParams(i, analogValues[i]); 681 | 682 | } 683 | analogValuesLag[i] = analogValues[i]; 684 | } 685 | } 686 | 687 | //Switches/EncoderBtn 688 | for (int i = 0; i < 5; ++i){ 689 | if (btnSwBouncers[i].update() || firstRun){ 690 | if (i<4){ 691 | rawVals[i + 16] = digitalRead(btnSwPins[i]); 692 | } 693 | switch (i) { 694 | case 0: 695 | setVoceOneShape(digitalRead(btnSwPins[i])); 696 | break; 697 | case 1: 698 | setVoceTwoShape(digitalRead(btnSwPins[i])); 699 | break; 700 | case 2: 701 | setVoceThreeShape(digitalRead(btnSwPins[i])); 702 | break; 703 | case 3: 704 | setLfoShape(digitalRead(btnSwPins[i])); 705 | break; 706 | case 4: 707 | if (!digitalRead(btnSwPins[i])){ 708 | clearTimeStamp = millis(); 709 | 710 | neoPixelsOff(); 711 | menuCount++; 712 | if (menuCount > 4){ 713 | menuCount = 0; 714 | checkSeqStart(); 715 | } 716 | 717 | if (menuCount == 4){ 718 | seqRunning = false; 719 | seqEditMode = true; 720 | }else{ 721 | seqEditMode = false; 722 | } 723 | } 724 | break; 725 | } 726 | } 727 | } 728 | //CrearEverything 729 | if ((abs(millis() - clearTimeStamp) > 2000) && !digitalRead(20)){ 730 | clearEverything(); 731 | clearTimeStamp = millis(); 732 | } 733 | 734 | //Voice Stuff 735 | for (int i = 0; i < 4; ++i){ 736 | 737 | if(i == 0){//VoiceA 738 | voiceOneA.frequency(VoiceFreq[i] * octave[octaveKey] * lfoPitchMod); 739 | voiceTwoA.frequency(VoiceFreq[i] * octave[octaveKey] * plusDetune * lfoPitchMod); 740 | voiceThreeA.frequency(VoiceFreq[i] * octave[octaveKey] * minusDetune * lfoPitchMod); 741 | //Env 742 | if(voices[i]){ 743 | envelopeA.amplitude(VoiceVel[i], attackTime); 744 | filterEnvA.amplitude(VoiceVel[i],filterEnvAttack); 745 | }else{ 746 | envelopeA.amplitude(0, releaseTime); 747 | filterEnvA.amplitude(-1,filterEnvRelease); 748 | } 749 | }else if(i == 1){//VoiceB 750 | voiceOneB.frequency(VoiceFreq[i] * octave[octaveKey] * lfoPitchMod); 751 | voiceTwoB.frequency(VoiceFreq[i] * octave[octaveKey] * plusDetune * lfoPitchMod); 752 | voiceThreeB.frequency(VoiceFreq[i] * octave[octaveKey] * minusDetune * lfoPitchMod); 753 | //Env 754 | if(voices[i]){ 755 | envelopeB.amplitude(VoiceVel[i], attackTime); 756 | filterEnvB.amplitude(VoiceVel[i],filterEnvAttack); 757 | }else{ 758 | envelopeB.amplitude(0, releaseTime); 759 | filterEnvB.amplitude(-1,filterEnvRelease); 760 | } 761 | }else if(i == 2){//VoiceC 762 | voiceOneC.frequency(VoiceFreq[i] * octave[octaveKey] * lfoPitchMod); 763 | voiceTwoC.frequency(VoiceFreq[i] * octave[octaveKey] * plusDetune * lfoPitchMod); 764 | voiceThreeC.frequency(VoiceFreq[i] * octave[octaveKey] * minusDetune * lfoPitchMod); 765 | //Env 766 | if(voices[i]){ 767 | envelopeC.amplitude(VoiceVel[i], attackTime); 768 | filterEnvC.amplitude(VoiceVel[i],filterEnvAttack); 769 | }else{ 770 | envelopeC.amplitude(0, releaseTime); 771 | filterEnvC.amplitude(-1,filterEnvRelease); 772 | } 773 | }else if(i == 3){//VoiceD 774 | voiceOneD.frequency(VoiceFreq[i] * octave[octaveKey] * lfoPitchMod); 775 | voiceTwoD.frequency(VoiceFreq[i] * octave[octaveKey] * plusDetune * lfoPitchMod); 776 | voiceThreeD.frequency(VoiceFreq[i] * octave[octaveKey] * minusDetune * lfoPitchMod); 777 | //Env 778 | if(voices[i]){ 779 | envelopeD.amplitude(VoiceVel[i], attackTime); 780 | filterEnvD.amplitude(VoiceVel[i],filterEnvAttack); 781 | }else{ 782 | envelopeD.amplitude(0, releaseTime); 783 | filterEnvD.amplitude(-1,filterEnvRelease); 784 | } 785 | } 786 | } 787 | 788 | //LFO 789 | LFO1.frequency(lfoFreq); 790 | LFO1.amplitude(lfoAmt); 791 | //Filter 792 | filterA.frequency(filterFreq); 793 | filterA.resonance(filterRes); 794 | filterB.frequency(filterFreq); 795 | filterB.resonance(filterRes); 796 | filterC.frequency(filterFreq); 797 | filterC.resonance(filterRes); 798 | filterD.frequency(filterFreq); 799 | filterD.resonance(filterRes); 800 | //LFO2 801 | if(lfoPeak.available()){ 802 | lfoPitchMod = lfoPeak.read() + .5; 803 | } 804 | //voiceA 805 | if (peakA.available()){ 806 | voiceAPeak = peakA.read(); 807 | ampArray[0] = voiceAPeak; 808 | } 809 | //voiceB 810 | if (peakB.available()){ 811 | voiceBPeak = peakB.read(); 812 | ampArray[1] = voiceBPeak; 813 | } 814 | //voiceC 815 | if (peakC.available()){ 816 | voiceCPeak = peakC.read(); 817 | ampArray[2] = voiceCPeak; 818 | } 819 | //voiceD 820 | if (peakD.available()){ 821 | voiceDPeak = peakD.read(); 822 | ampArray[3] = voiceDPeak; 823 | } 824 | //FinalPeak 825 | if (finalPeak.available()){ 826 | finalAmp = finalPeak.read(); 827 | } 828 | 829 | firstRun = false; 830 | 831 | } 832 | 833 | //START MIDI 834 | void OnControlChange(byte channel, byte control, byte value){ 835 | setSynthParams(control-1, value * 8.055); 836 | rawVals[control-1] = value * 8.055; 837 | paramLocks[control-1] = true; 838 | } 839 | 840 | void OnNoteOn(byte channel, byte note, byte velocity){ 841 | float freq = 440.0 * powf(2.0, (float)(note - 69) * 0.08333333); 842 | float vel = (float)velocity/127; 843 | startVoice(freq, vel); 844 | } 845 | 846 | void OnNoteOff(byte channel, byte note, byte velocity){ 847 | float freq = 440.0 * powf(2.0, (float)(note - 69) * 0.08333333); 848 | endVoice(freq); 849 | } 850 | //END MIDI 851 | 852 | 853 | void startVoice(float frequency, float velocity){ 854 | // for (int i = 0; i < 4; ++i){ 855 | // if (!voices[i]){ 856 | // voices[i] = frequency; 857 | // VoiceFreq[i] = frequency; 858 | // VoiceVel[i] = velocity; 859 | // if (voices[i]){ 860 | // return; 861 | // } 862 | // } 863 | // } 864 | 865 | voiceNum = lowestAmp(); 866 | //if voice is already in use scan to next voice 867 | for (int i = 0; i < 4; ++i){ 868 | if (voices[voiceNum]){ 869 | voiceNum++; 870 | if (voiceNum > 3){ 871 | voiceNum = 0; 872 | } 873 | } 874 | } 875 | //Assign (unused voice || lowest voice) 876 | voices[voiceNum] = frequency; 877 | VoiceFreq[voiceNum] = voices[voiceNum]; 878 | VoiceVel[voiceNum] = velocity; 879 | 880 | } 881 | 882 | void endVoice(float frequency){ 883 | for (int i = 0; i < 4; ++i){ 884 | if(VoiceFreq[i] == frequency){ 885 | voices[i] = 0; 886 | } 887 | } 888 | } 889 | 890 | int lowestAmp(){ 891 | int index = 0; 892 | for (int i = 0; i < 4; i++){ 893 | if (ampArray[i] < ampArray[index]) { 894 | index = i; 895 | } 896 | } 897 | return index; 898 | } 899 | 900 | void setMuxPin(int channel){ 901 | int controlPin[] = {s0, s1, s2, s3}; 902 | 903 | int muxChannel[16][4]={ 904 | {0,0,0,0}, //channel 0 905 | {1,0,0,0}, //channel 1 906 | {0,1,0,0}, //channel 2 907 | {1,1,0,0}, //channel 3 908 | {0,0,1,0}, //channel 4 909 | {1,0,1,0}, //channel 5 910 | {0,1,1,0}, //channel 6 911 | {1,1,1,0}, //channel 7 912 | {0,0,0,1}, //channel 8 913 | {1,0,0,1}, //channel 9 914 | {0,1,0,1}, //channel 10 915 | {1,1,0,1}, //channel 11 916 | {0,0,1,1}, //channel 12 917 | {1,0,1,1}, //channel 13 918 | {0,1,1,1}, //channel 14 919 | {1,1,1,1} //channel 15 920 | }; 921 | 922 | //loop through the 4 sig 923 | for(int i = 0; i < 4; i ++){ 924 | digitalWrite(controlPin[i], muxChannel[channel][i]); 925 | } 926 | } 927 | void loadPreset(int number){ 928 | String currentPreset = fileNames[number]; 929 | 930 | myFile = SD.open(currentPreset.c_str()); 931 | 932 | if (myFile) { 933 | for (int i = 0; i < 20; i++) { 934 | int input = myFile.parseFloat(); 935 | rawVals[i] = input; 936 | if (i < 16){ 937 | paramLocks[i] = true; 938 | } 939 | } 940 | // close the file: 941 | myFile.close(); 942 | //set all them params 943 | for (int i = 0; i < 20; ++i){ 944 | setSynthParams(i, rawVals[i]); 945 | } 946 | } else { 947 | // if the file didn't open, print an error: 948 | Serial.println("error opening file"); 949 | } 950 | } 951 | 952 | void savePreset(int number){ 953 | String currentPreset = fileNames[number]; 954 | //Remove File 955 | if (SD.exists(currentPreset.c_str())) { 956 | Serial.println("remove the file"); 957 | SD.remove(currentPreset.c_str()); 958 | } 959 | //open File 960 | myFile = SD.open(currentPreset.c_str(), FILE_WRITE); 961 | //if the file opened okay, write to it: 962 | if (myFile) { 963 | for (int i = 0; i < 20; ++i){ 964 | myFile.println(rawVals[i]); 965 | } 966 | // close the file: 967 | myFile.close(); 968 | Serial.print("wrote to file"); 969 | } else { 970 | // if the file didn't open, print an error: 971 | Serial.println("error opening file"); 972 | } 973 | } 974 | 975 | void neoPixelsOff(){ 976 | for (int i = 0; i < 12; ++i){ 977 | pixels.setPixelColor(i, pixels.Color(0, 0, 0)); 978 | } 979 | } 980 | 981 | void setVoceOneShape (bool saw){ 982 | if (saw){ 983 | voiceOneA.begin(WAVEFORM_SAWTOOTH); 984 | voiceOneB.begin(WAVEFORM_SAWTOOTH); 985 | voiceOneC.begin(WAVEFORM_SAWTOOTH); 986 | voiceOneD.begin(WAVEFORM_SAWTOOTH); 987 | }else{ 988 | voiceOneA.begin(WAVEFORM_SQUARE); 989 | voiceOneB.begin(WAVEFORM_SQUARE); 990 | voiceOneC.begin(WAVEFORM_SQUARE); 991 | voiceOneD.begin(WAVEFORM_SQUARE); 992 | } 993 | } 994 | void setVoceTwoShape (bool saw){ 995 | if (saw){ 996 | voiceTwoA.begin(WAVEFORM_SAWTOOTH); 997 | voiceTwoB.begin(WAVEFORM_SAWTOOTH); 998 | voiceTwoC.begin(WAVEFORM_SAWTOOTH); 999 | voiceTwoD.begin(WAVEFORM_SAWTOOTH); 1000 | }else{ 1001 | voiceTwoA.begin(WAVEFORM_SQUARE); 1002 | voiceTwoB.begin(WAVEFORM_SQUARE); 1003 | voiceTwoC.begin(WAVEFORM_SQUARE); 1004 | voiceTwoD.begin(WAVEFORM_SQUARE); 1005 | } 1006 | } 1007 | void setVoceThreeShape (bool saw){ 1008 | if (saw){ 1009 | voiceThreeA.begin(WAVEFORM_TRIANGLE); 1010 | voiceThreeB.begin(WAVEFORM_TRIANGLE); 1011 | voiceThreeC.begin(WAVEFORM_TRIANGLE); 1012 | voiceThreeD.begin(WAVEFORM_TRIANGLE); 1013 | }else{ 1014 | voiceThreeA.begin(WAVEFORM_SQUARE); 1015 | voiceThreeB.begin(WAVEFORM_SQUARE); 1016 | voiceThreeC.begin(WAVEFORM_SQUARE); 1017 | voiceThreeD.begin(WAVEFORM_SQUARE); 1018 | } 1019 | } 1020 | void setLfoShape(bool sine){ 1021 | if (sine){ 1022 | LFO1.begin(WAVEFORM_SINE); 1023 | }else{ 1024 | LFO1.begin(WAVEFORM_SAWTOOTH_REVERSE); 1025 | } 1026 | } 1027 | void clearEverything(){ 1028 | neoPixelsOff(); 1029 | menuCount = 0; 1030 | seqRunning = false; 1031 | firstRun = true; 1032 | presetNumber = -1; 1033 | for (int i = 0; i < 16; ++i){ 1034 | paramLocks[i] = false; 1035 | } 1036 | for (int z = 0; z < 4; ++z){ 1037 | voices[z] = 0; 1038 | for (int j = 0; j < 8; ++j){ 1039 | seqFrequencies[z][j] = 0; 1040 | seqFrequenciesTwo[z][j] = 0; 1041 | } 1042 | } 1043 | } 1044 | void checkSeqStart(){ 1045 | //Check if any notes were entered, if so start sequence 1046 | //Also set seqLength based on notes entered 1047 | for (int i = 0; i < 8; ++i){ 1048 | if (seqFrequencies[0][i]){ 1049 | seqLength = 8; 1050 | } 1051 | } 1052 | for (int i = 0; i < 8; ++i){ 1053 | if (seqFrequencies[1][i]){ 1054 | seqLength = 16; 1055 | } 1056 | } 1057 | for (int i = 0; i < 8; ++i){ 1058 | if (seqFrequencies[2][i]){ 1059 | seqLength = 24; 1060 | } 1061 | } 1062 | for (int i = 0; i < 8; ++i){ 1063 | if (seqFrequencies[3][i]){ 1064 | seqLength = 32; 1065 | } 1066 | } 1067 | 1068 | for (int i = 0; i < 4; ++i){ 1069 | voices[i] = 0; 1070 | for (int k = 0; k < 8; ++k){ 1071 | if (seqFrequencies[i][k] > 0){ 1072 | seqRunning = true; 1073 | break; 1074 | } 1075 | } 1076 | if (seqRunning){ 1077 | break; 1078 | } 1079 | } 1080 | 1081 | if (seqInterval == 0){ 1082 | encoderValue = 1700; 1083 | seqInterval = 300; 1084 | metronome.interval(seqInterval); 1085 | }else{ 1086 | encoderValue = 2000 - seqInterval; 1087 | } 1088 | 1089 | lastEncoded = encoded; 1090 | seqStep = 0; 1091 | seqPage = 0; 1092 | metronome.reset(); 1093 | } 1094 | 1095 | void updateEncoder(){ 1096 | int MSB = digitalRead(encoderPin1); //MSB = most significant bit 1097 | int LSB = digitalRead(encoderPin2); //LSB = least significant bit 1098 | 1099 | encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number 1100 | int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value 1101 | 1102 | if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; 1103 | if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; 1104 | 1105 | 1106 | if (encoderValue < 0){ 1107 | encoderValue = 0; 1108 | } 1109 | if (seqEditMode){ 1110 | if (encoderValue > 124){ 1111 | encoderValue = 124; 1112 | } 1113 | }else if(seqRunning){ 1114 | if (encoderValue > 2000){ 1115 | encoderValue = 2000; 1116 | } 1117 | } 1118 | 1119 | scaledEncVal = encoderValue/4; 1120 | 1121 | lastEncoded = encoded; //store this value for next time 1122 | 1123 | } 1124 | int smoothRead(int pin){ 1125 | int vals[8]; //array that stores 8 readings. 1126 | for(int i = 0; i < 8; i++){ 1127 | vals[i] = touchRead(pin); //takes 8 readings. 1128 | } 1129 | float smooth = (vals[0] + vals[1] + vals[2] + vals[3] + vals[4] + vals[5] + vals[6] + vals[7]) / 8; 1130 | return smooth; 1131 | } 1132 | 1133 | void setSynthParams(int number, float value){ 1134 | 1135 | if (number < 4){ 1136 | voiceMixerA.gain(number, value/2046); 1137 | voiceMixerB.gain(number, value/2046); 1138 | voiceMixerC.gain(number, value/2046); 1139 | voiceMixerD.gain(number, value/2046); 1140 | }else if(number == 4){ 1141 | LFO2.frequency(value/130); 1142 | }else if(number == 5){ 1143 | LFO2.amplitude(value/32736); 1144 | }else if(number == 6){ 1145 | masterDetune = value; 1146 | plusDetune = map(masterDetune, 0, 1023, 1, 1.5); 1147 | minusDetune = map(masterDetune, 0, 1023, 1, .75); 1148 | }else if(number == 7){ 1149 | 1150 | if (seqRunning){ 1151 | lfoIndex = value/204.6; 1152 | lfoIndex = constrain(lfoIndex, 0, 4); 1153 | lfoFreq = (1/seqInterval)*lfoTimeMathArray[lfoIndex]; 1154 | }else{ 1155 | lfoFreq = value/120; 1156 | } 1157 | }else if(number == 8){ 1158 | lfoAmt = value/1023; 1159 | }else if(number == 9){ 1160 | attackTime = value * 2; 1161 | }else if(number == 10){ 1162 | releaseTime = value * 2; 1163 | }else if(number == 11){ 1164 | filterEnvAttack = value * 2; 1165 | }else if(number == 12){ 1166 | filterEnvRelease = value * 2; 1167 | }else if(number == 13){ 1168 | filterFreq = (value * 10) + 100; 1169 | }else if(number == 14){ 1170 | filterRes = (value / 255) + 1.10; 1171 | }else if(number == 15){ 1172 | octaveKey = value/255; 1173 | octaveKey = constrain(octaveKey, 0, 3); 1174 | }else if(number == 16){ 1175 | setVoceOneShape(value); 1176 | }else if(number == 17){ 1177 | setVoceTwoShape(value); 1178 | }else if(number == 18){ 1179 | setVoceThreeShape(value); 1180 | }else if (number == 19){ 1181 | setLfoShape(value); 1182 | } 1183 | } 1184 | -------------------------------------------------------------------------------- /Arcus/Arcus.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // GUItool: begin automatically generated code 8 | AudioSynthWaveform snareSMod; //xy=66,311.96427059173584 9 | AudioSynthWaveform snareNAmpMod; //xy=94.0000114440918,254.96426916122437 10 | AudioSynthNoiseWhite snareN; //xy=111.00001525878906,217.71426725387573 11 | AudioSynthWaveformModulated snareS; //xy=194.7500114440918,318.2142701148987 12 | AudioSynthWaveformDc snareSEnv; //xy=199.7500114440918,360.7142701148987 13 | AudioEffectMultiply snareNMulti; //xy=246.25003814697266,226.71426844596863 14 | AudioSynthWaveformDc snareNEnv; //xy=254.75000762939453,266.96426939964294 15 | AudioEffectMultiply snareSMult; //xy=352.2500114440918,334.4642701148987 16 | AudioEffectMultiply snareNMultF; //xy=401.00000762939453,249.4642686843872 17 | AudioSynthWaveformDc hhEnv; //xy=416.32140350341797,415.6427822113037 18 | AudioSynthNoiseWhite hhNoise; //xy=418.32140350341797,376.6427822113037 19 | AudioSynthSimpleDrum kickClick; //xy=517.1785736083984,134.92853355407715 20 | AudioSynthSimpleDrum kickOne; //xy=519.1785736083984,100.92853355407715 21 | AudioPlaySdRaw playSdRaw1; //xy=532.8571270533971,527.1428428377425 22 | AudioSynthWaveformDc sampleEnv; //xy=538.57139478411,587.142841407231 23 | AudioMixer4 snareMixer; //xy=556.0000076293945,275.21427059173584 24 | AudioEffectMultiply hhMulti; //xy=556.321403503418,399.6427822113037 25 | AudioInputI2S i2s2; //xy=621.4285354614258,681.4285926818848 26 | AudioMixer4 kickMixer; //xy=663.1785736083984,136.17853546142578 27 | AudioFilterStateVariable hhFilter; //xy=688.3214111328125,392.1427803039551 28 | AudioFilterStateVariable snareFilter; //xy=711.2500076293945,280.7142696380615 29 | AudioEffectMultiply sampMulti; //xy=737.1428527832031,561.4285583496094 30 | AudioSynthSimpleDrum tom; //xy=745.2857273646763,489.99997111729203 31 | AudioMixer4 extMixer; //xy=787.1428527832031,704.2856826782227 32 | AudioMixer4 drumMixer; //xy=915.8214569091797,302.57140731811523 33 | AudioMixer4 drumInstMixer; //xy=967.142857142857,564.2857110159737 34 | AudioRecordQueue queue1; //xy=975.7142868041992,775.7142872810364 35 | AudioAnalyzePeak peak1; //xy=977.1428031921387,719.9999771118164 36 | AudioEffectBitcrusher bitcrusher1; //xy=1098.5714111328125,442.85716342926025 37 | AudioFilterStateVariable delayFilter; //xy=1233.392910003662,586.2499732971191 38 | AudioEffectDelay delay1; //xy=1234.642910003662,698.7499694824219 39 | AudioMixer4 delayMixer; //xy=1243.392910003662,498.7499694824219 40 | AudioFilterStateVariable globalFilter; //xy=1427.1427841186523,501.4285583496094 41 | AudioSynthWaveform pulseOut; //xy=1482.8571428571427,571.4285714285713 42 | AudioMixer4 pulseOutMixer; //xy=1648.5714721679688,522.8571395874023 43 | AudioOutputI2S i2s1; //xy=1814.285717010498,464.28577995300293 44 | AudioConnection patchCord1(snareSMod, 0, snareS, 0); 45 | AudioConnection patchCord2(snareNAmpMod, 0, snareNMulti, 1); 46 | AudioConnection patchCord3(snareN, 0, snareNMulti, 0); 47 | AudioConnection patchCord4(snareS, 0, snareSMult, 0); 48 | AudioConnection patchCord5(snareSEnv, 0, snareSMult, 1); 49 | AudioConnection patchCord6(snareNMulti, 0, snareNMultF, 0); 50 | AudioConnection patchCord7(snareNEnv, 0, snareNMultF, 1); 51 | AudioConnection patchCord8(snareSMult, 0, snareMixer, 1); 52 | AudioConnection patchCord9(snareNMultF, 0, snareMixer, 0); 53 | AudioConnection patchCord10(hhEnv, 0, hhMulti, 1); 54 | AudioConnection patchCord11(hhNoise, 0, hhMulti, 0); 55 | AudioConnection patchCord12(kickClick, 0, kickMixer, 1); 56 | AudioConnection patchCord13(kickOne, 0, kickMixer, 0); 57 | AudioConnection patchCord14(playSdRaw1, 0, sampMulti, 0); 58 | AudioConnection patchCord15(sampleEnv, 0, sampMulti, 1); 59 | AudioConnection patchCord16(snareMixer, 0, snareFilter, 0); 60 | AudioConnection patchCord17(hhMulti, 0, hhFilter, 0); 61 | AudioConnection patchCord18(i2s2, 0, extMixer, 0); 62 | AudioConnection patchCord19(i2s2, 0, drumInstMixer, 2); 63 | AudioConnection patchCord20(i2s2, 1, extMixer, 1); 64 | AudioConnection patchCord21(kickMixer, 0, drumMixer, 0); 65 | AudioConnection patchCord22(hhFilter, 2, drumMixer, 2); 66 | AudioConnection patchCord23(snareFilter, 1, drumMixer, 1); 67 | AudioConnection patchCord24(sampMulti, 0, drumInstMixer, 1); 68 | AudioConnection patchCord25(tom, 0, drumMixer, 3); 69 | AudioConnection patchCord26(extMixer, queue1); 70 | AudioConnection patchCord27(extMixer, peak1); 71 | AudioConnection patchCord28(extMixer, 0, drumInstMixer, 3); 72 | AudioConnection patchCord29(drumMixer, 0, drumInstMixer, 0); 73 | AudioConnection patchCord30(drumInstMixer, bitcrusher1); 74 | AudioConnection patchCord31(bitcrusher1, 0, delayMixer, 0); 75 | AudioConnection patchCord32(delayFilter, 0, delayMixer, 3); 76 | AudioConnection patchCord33(delay1, 0, delayFilter, 0); 77 | AudioConnection patchCord34(delayMixer, delay1); 78 | AudioConnection patchCord35(delayMixer, 0, globalFilter, 0); 79 | AudioConnection patchCord36(globalFilter, 0, pulseOutMixer, 0); 80 | AudioConnection patchCord37(globalFilter, 0, i2s1, 0); 81 | AudioConnection patchCord38(pulseOut, 0, pulseOutMixer, 1); 82 | AudioConnection patchCord39(pulseOutMixer, 0, i2s1, 1); 83 | AudioControlSGTL5000 sgtl5000_1; //xy=1564.2856903076172,354.2857303619385 84 | // GUItool: end automatically generated code 85 | 86 | 87 | 88 | 89 | ///Arcus 90 | ///Teensy 3.2 91 | //USB Type: Serial + MIDI 92 | /////////////////////////////////////////////////////////////////////////////////////// 93 | //===================================================================================// 94 | 95 | 96 | #define FASTLED_ALLOW_INTERRUPTS 0 97 | #include 98 | #include 99 | 100 | //SD 101 | #define SDCARD_CS_PIN 10 102 | #define SDCARD_MOSI_PIN 7 103 | #define SDCARD_SCK_PIN 14 104 | 105 | //peak detect stuff 106 | float thresholdMin = .5; // minimum reading, avoid noise and false starts 107 | const int peakTrackMillis = 2; 108 | const int aftershockMillis = 15; // 5aftershocks & vibration reject 109 | 110 | //leds 111 | #define DATA_PIN 0 112 | #define NUM_LEDS 32 113 | #define COLOR_ORDER GRB 114 | CRGB leds[NUM_LEDS]; 115 | int blinkBrightness; 116 | 117 | //Mux control pins 118 | int s0 = 2; 119 | int s1 = 3; 120 | int s2 = 4; 121 | int s3 = 5; 122 | //Mux in "SIG" pin 123 | int SIG_pin = 1; 124 | int SIG_pin_two = 15; 125 | unsigned long readTime; 126 | unsigned long prevReadTime; 127 | bool readFlag; 128 | int readCount = 0; 129 | 130 | //btns 131 | int btnStatus[16]; 132 | int prevBtnStatus[16]; 133 | int extBtnStatus[2] = {1,1}; 134 | int prevExtBtnStatus[2] = {1,1}; 135 | 136 | 137 | bool transportDown; 138 | bool btnDown; 139 | unsigned long clearTimeStamp; 140 | unsigned long menuTmStp; 141 | //Knobs 142 | float analogValues[16]; 143 | float analogValuesLag[16]; 144 | bool analogOpen[16]; 145 | unsigned long analogOpenTime[16]; 146 | 147 | //DrumVars 148 | bool firstRun = true; 149 | //Levels 150 | float levels[5]; 151 | //Decays 152 | int decays[5]; 153 | //Pitchs 154 | float pitches[5]; 155 | int samplePitch; 156 | //fx sends 157 | float fxSendAmt[5]; 158 | // int for bits 159 | int crushBits = 44100; 160 | 161 | //seqTriggers//params 162 | bool trigs[5][64]; 163 | float params[5][64][7]; 164 | int instIndex; 165 | int prevInstIndex = -1; 166 | 167 | //sample names 168 | const char *wavSamples[16] = { 169 | "1.RAW","2.RAW","3.RAW","4.RAW", 170 | "5.RAW","6.RAW","7.RAW","8.RAW", 171 | "9.RAW","10.RAW","11.RAW","12.RAW", 172 | "13.RAW","14.RAW","15.RAW","16.RAW", 173 | }; 174 | bool sampleSlot[16]; 175 | bool recSampMode; 176 | bool recArmed; 177 | int sampIndex; 178 | float extPeakVal; 179 | bool peakReached; 180 | bool recording; 181 | File frec; 182 | unsigned long recTimeStamp; 183 | unsigned long peakTimeStamp; 184 | 185 | 186 | //sequencer 187 | Metro metronome = Metro(300); 188 | int metroInt = 300; 189 | int seqStep; 190 | int prevSeqStep; 191 | int ledSeqStep; 192 | int seqPage; 193 | int seqPageArray[4] = {0,16,32,48}; 194 | bool recAutMode = false; 195 | bool seqPlaying = false; 196 | bool pageChange; 197 | int stepLimit = 15; 198 | int syncNumber = 7; 199 | //slave pulse 200 | bool slaveClock; 201 | unsigned long lastPulse; 202 | bool doubleStep; 203 | unsigned long intervalTime; 204 | //slave MIDI 205 | byte counter; 206 | byte CLOCK = 248; 207 | byte START = 250; 208 | byte CONTINUE = 251; 209 | byte STOP = 252; 210 | //Master pulse 211 | bool sendPulse; 212 | bool receivePulse; 213 | unsigned long pulseSentTime; 214 | bool pulseSent; 215 | 216 | 217 | int colorArray[5][3] = { 218 | {255,0,0,}, 219 | {0,255,255}, 220 | {255,0,255}, 221 | {255,255,0}, 222 | {0,0,255}, 223 | }; 224 | 225 | //preset stuff 226 | const int chipSelect = 10; 227 | int presetNumber = -1; 228 | File myFile; 229 | String fileNames[4] = {"1.txt","2.txt","3.txt","4.txt"}; 230 | int currentPreset; 231 | bool presetLoading; 232 | float inputOne; 233 | float inputTwo; 234 | 235 | 236 | void setup() { 237 | Serial.begin(9600); 238 | 239 | LEDS.addLeds(leds,NUM_LEDS); 240 | LEDS.setBrightness(128); 241 | 242 | 243 | //MIDI CLOCK 244 | usbMIDI.setHandleRealTimeSystem(RealTimeSystem); 245 | AudioMemory(116); 246 | 247 | //Kick 248 | kickOne.frequency(60); 249 | kickOne.length(1000); 250 | kickOne.secondMix(.5); 251 | kickOne.pitchMod(.7); 252 | kickClick.frequency(1000); 253 | kickClick.length(10); 254 | kickClick.pitchMod(.9); 255 | //Snare 256 | snareN.amplitude(1); 257 | snareNAmpMod.begin(1,40,WAVEFORM_SAWTOOTH_REVERSE); 258 | snareSMod.begin(.7,50,WAVEFORM_SAWTOOTH_REVERSE); 259 | snareS.begin(1,50,WAVEFORM_SQUARE); 260 | snareFilter.frequency(1500); 261 | snareFilter.resonance(2); 262 | //High Hat 263 | hhNoise.amplitude(.7); 264 | hhFilter.frequency(2000); 265 | hhFilter.resonance(4); 266 | //Tom 267 | tom.frequency(200); 268 | tom.length(500); 269 | tom.secondMix(1); 270 | tom.pitchMod(.55); 271 | 272 | //Bits 273 | bitcrusher1.bits(16); 274 | bitcrusher1.sampleRate(44100); 275 | //Delay 276 | delayMixer.gain(3,0); 277 | delayFilter.frequency(5000); 278 | //Global Filter 279 | globalFilter.frequency(15000); 280 | globalFilter.resonance(2); 281 | 282 | //pulse Out 283 | pulseOut.begin(1, 30, WAVEFORM_PULSE); 284 | pulseOut.pulseWidth(0); 285 | //Initialize values 286 | for(int i=0; i<5; i++){ 287 | levels[i] = 1; 288 | pitches[i] = 1; 289 | decays[i] = 200; 290 | } 291 | 292 | 293 | SPI.setMOSI(SDCARD_MOSI_PIN); 294 | SPI.setSCK(SDCARD_SCK_PIN); 295 | if (!(SD.begin(SDCARD_CS_PIN))) { 296 | // stop here, but print a message repetitively 297 | while (1) { 298 | Serial.println("Unable to access the SD card"); 299 | delay(500); 300 | } 301 | } 302 | for(int i=0; i<16; i++){ 303 | if (SD.exists(wavSamples[i])) { 304 | sampleSlot[i] = true; 305 | } 306 | } 307 | //peak mixer settings 308 | sendPulseCheck(); 309 | receivePulseCheck(); 310 | resetSeq(); 311 | 312 | sgtl5000_1.enable(); 313 | //sgtl5000_1.volume(.1); 314 | sgtl5000_1.lineOutLevel(29); 315 | sgtl5000_1.adcHighPassFilterDisable(); 316 | 317 | 318 | //Mux 319 | pinMode(s0, OUTPUT); 320 | pinMode(s1, OUTPUT); 321 | pinMode(s2, OUTPUT); 322 | pinMode(s3, OUTPUT); 323 | pinMode(SIG_pin, INPUT); 324 | pinMode(SIG_pin_two, INPUT); 325 | digitalWrite(s0, LOW); 326 | digitalWrite(s1, LOW); 327 | digitalWrite(s2, LOW); 328 | digitalWrite(s3, LOW); 329 | 330 | 331 | //led starup 332 | for(int i=0; i -1){ 343 | if (seqPlaying && params[inst][seqStep][0] > 0 && !(analogOpen[0] && instIndex == inst)){ 344 | levels[inst] = params[inst][seqStep][0]; 345 | } 346 | if (seqPlaying && params[inst][seqStep][1] > 0 && !(analogOpen[1] && instIndex == inst)){ 347 | decays[inst] = params[inst][seqStep][1]; 348 | } 349 | if (seqPlaying && params[inst][seqStep][2] > 0 && !(analogOpen[2] && instIndex == inst)){ 350 | pitches[inst] = params[inst][seqStep][2]; 351 | } 352 | } 353 | } 354 | void playKick(){ 355 | checkSeqStep(0); 356 | drumMixer.gain(0,levels[0]); 357 | kickOne.frequency((30*pitches[0]) + 20); 358 | kickClick.frequency(1000*pitches[0]); 359 | kickOne.length(decays[0]); 360 | kickClick.length((decays[0] / 100)+1); 361 | kickOne.noteOn(); 362 | kickClick.noteOn(); 363 | } 364 | void playSnare(){ 365 | checkSeqStep(1); 366 | drumMixer.gain(1,levels[1]/3); 367 | snareFilter.frequency((3000 * pitches[1]) + 50); 368 | snareSMod.frequency(50 * pitches[1]); 369 | snareS.frequency(150 * pitches[1]); 370 | snareNEnv.amplitude(1,0); 371 | snareNEnv.amplitude(0,decays[1]); 372 | snareSEnv.amplitude(1,0); 373 | snareSEnv.amplitude(0,decays[1] / 3); 374 | } 375 | void playHh(){ 376 | checkSeqStep(2); 377 | hhFilter.frequency(pitches[2] * 5000); 378 | drumMixer.gain(2,levels[2]); 379 | hhEnv.amplitude(.3,0); 380 | hhEnv.amplitude(0,decays[2]); 381 | } 382 | void playTom(){ 383 | checkSeqStep(3); 384 | drumMixer.gain(3,levels[3]); 385 | tom.length(decays[3]); 386 | tom.frequency((500*pitches[3]) + 10); 387 | tom.noteOn(); 388 | } 389 | void playSample(){ 390 | checkSeqStep(4); 391 | drumInstMixer.gain(1,levels[4]); 392 | sampleEnv.amplitude(1,0); 393 | int playSampIndex = (pitches[4] - 1); 394 | playSdRaw1.stop(); 395 | playSdRaw1.play(wavSamples[playSampIndex]); 396 | sampleEnv.amplitude(0,decays[4]); 397 | } 398 | 399 | void checkCrushBus(int inst){ 400 | if(seqStep > -1){ 401 | if (seqPlaying && params[inst][seqStep][3] > 0 && !analogOpen[3]){ 402 | fxSendAmt[0] = params[inst][seqStep][3]; 403 | } 404 | } 405 | bitcrusher1.sampleRate(fxSendAmt[0]); 406 | } 407 | void checkDelayBus(int inst){ 408 | if(seqStep > -1){ 409 | if (seqPlaying && params[inst][seqStep][4] > 0 && !analogOpen[4]){ 410 | fxSendAmt[1] = params[inst][seqStep][4]; 411 | } 412 | if (seqPlaying && params[inst][seqStep][5] > 0 && !analogOpen[5]){ 413 | fxSendAmt[2] = params[inst][seqStep][5]; 414 | } 415 | } 416 | delay1.delay(0,fxSendAmt[1]); 417 | delayMixer.gain(3,fxSendAmt[2]); 418 | } 419 | void checkGlobalFilterBus(int inst){ 420 | if(seqStep > -1){ 421 | if (seqPlaying && params[inst][seqStep][6] > 0 && !analogOpen[6]){ 422 | fxSendAmt[3] = params[inst][seqStep][6]; 423 | } 424 | } 425 | globalFilter.frequency((fxSendAmt[3] * 12)+60); 426 | } 427 | 428 | void setLevels(float value){ 429 | levels[instIndex] = value / 1023; 430 | if(seqStep > -1){ 431 | //if(recAutMode && !seqPlaying && btnDown){ 432 | if(!seqPlaying && btnDown){ 433 | params[instIndex][seqStep][0] = levels[instIndex]; 434 | }else if(seqPlaying && recAutMode){ 435 | params[instIndex][seqStep][0] = levels[instIndex]; 436 | } 437 | } 438 | } 439 | void setDecays(int value){ 440 | decays[instIndex] = value; 441 | if(seqStep > -1){ 442 | if(!seqPlaying && btnDown){ 443 | params[instIndex][seqStep][1] = decays[instIndex]; 444 | }else if(seqPlaying && recAutMode){ 445 | params[instIndex][seqStep][1] = decays[instIndex]; 446 | } 447 | } 448 | } 449 | void setPitches(float value){ 450 | pitches[instIndex] = value / 511; 451 | if(instIndex == 4){ 452 | samplePitch = value / 63.9; 453 | pitches[instIndex] = samplePitch + 1; 454 | } 455 | if(seqStep > -1){ 456 | if(!seqPlaying && btnDown){ 457 | params[instIndex][seqStep][2] = pitches[instIndex]; 458 | }else if(seqPlaying && recAutMode){ 459 | params[instIndex][seqStep][2] = pitches[instIndex]; 460 | } 461 | } 462 | } 463 | void setfxSend(int knob, int paramNumber, float value, int scaler){ 464 | fxSendAmt[knob] = value / scaler; 465 | if(seqStep > -1){ 466 | if(!seqPlaying && btnDown){ 467 | for(int i=0; i<5; i++){ 468 | params[i][seqStep][paramNumber] = fxSendAmt[knob]; 469 | } 470 | }else if(seqPlaying && recAutMode){ 471 | for(int i=0; i<5; i++){ 472 | params[i][seqStep][paramNumber] = fxSendAmt[knob]; 473 | } 474 | } 475 | } 476 | } 477 | 478 | 479 | void loop() { 480 | usbMIDI.read(); 481 | checkDelayBus(0); 482 | checkCrushBus(0); 483 | checkGlobalFilterBus(0); 484 | 485 | readTime = millis(); 486 | setMuxPin(readCount); 487 | 488 | if((readTime - prevReadTime) > 5){ 489 | analogValues[readCount] = analogRead(SIG_pin_two); 490 | btnStatus[readCount] = digitalRead(SIG_pin); 491 | if(readCount == 9 || readCount == 10){ 492 | extBtnStatus[readCount-9] = digitalRead(SIG_pin_two); 493 | } 494 | readCount++; 495 | if(readCount > 15){ 496 | readCount = 0; 497 | } 498 | prevReadTime = readTime; 499 | } 500 | 501 | //Record Samples 502 | if(recSampMode){ 503 | if(peak1.available()){ 504 | extPeakVal = peak1.read(); 505 | int ledPeak = extPeakVal * 16; 506 | int ledThresh = constrain(thresholdMin * 16,0,15); 507 | 508 | for(int i=0; i<16; i++){ 509 | if(i 2000) && recording){ 546 | stopRecording(); 547 | } 548 | 549 | //mux 550 | if(!recording){ 551 | for (int i = 0; i < 16; ++i){ 552 | //btns 553 | if ((abs(btnStatus[i] - prevBtnStatus[i]) > 0)){ 554 | if(recSampMode){ 555 | if (btnStatus[i] == LOW && prevBtnStatus[i] == HIGH){ 556 | sampIndex = i; 557 | //delete sample if present 558 | if (SD.exists(wavSamples[sampIndex]) && !recording) { 559 | Serial.print("Deleted: "); 560 | Serial.println(sampIndex); 561 | SD.remove(wavSamples[sampIndex]); 562 | sampleSlot[sampIndex] = false; 563 | } 564 | lightsOut(32); 565 | leds[sampIndex+16].setRGB(255, 0, 0); 566 | recArmed = true; 567 | peakReached = false; 568 | } 569 | }else{ 570 | if (btnStatus[i] == LOW && prevBtnStatus[i] == HIGH){ 571 | if(transportDown){ 572 | if(i == 0){ 573 | seqPlaying = !seqPlaying; 574 | countSteps(); 575 | resetSeq(); 576 | } 577 | if(i > 3 && i < 8){ 578 | syncSettings(i); 579 | }else if (i > 7 && i < 12){ 580 | savePreset(i-8); 581 | currentPreset = i-8; 582 | }else if (i > 11){ 583 | for(int i=0; i<4; i++){ 584 | leds[i+28].setRGB(0,0,0); 585 | } 586 | loadPreset(i-12); 587 | currentPreset = i-12; 588 | } 589 | }else{ 590 | if(!trigs[instIndex][i+seqPage]){ 591 | if(!presetLoading){ 592 | switch (instIndex) { 593 | case 0: 594 | playKick(); 595 | break; 596 | case 1: 597 | playSnare(); 598 | break; 599 | case 2: 600 | playHh(); 601 | break; 602 | case 3: 603 | playTom(); 604 | break; 605 | case 4: 606 | playSample(); 607 | break; 608 | } 609 | } 610 | if(!seqPlaying){ 611 | seqStep = i+seqPage; 612 | //Serial.print("setStep: "); 613 | btnDown = true; 614 | } 615 | } 616 | trigs[instIndex][i+seqPage] = !trigs[instIndex][i+seqPage]; 617 | } 618 | }else{ 619 | btnDown = false; 620 | leds[i+16].setRGB(0, 0, 0); 621 | } 622 | } 623 | prevBtnStatus[i] = btnStatus[i]; 624 | } 625 | // Knobs 626 | if(i<9){ 627 | if ((abs(analogValues[i] - analogValuesLag[i]) > 20) || (!seqPlaying && recAutMode)){ 628 | analogOpen[i] = true; 629 | } 630 | 631 | if ((analogOpen[i] && (abs(analogValues[i] - analogValuesLag[i]) > 3)) || firstRun || (btnDown && i < 7)){ 632 | analogOpenTime[i] = millis(); 633 | // Serial.print(i); 634 | // Serial.print(" : "); 635 | // Serial.println(analogValues[i]); 636 | switch (i) { 637 | case 0: 638 | //Level 639 | setLevels(analogValues[i]); 640 | break; 641 | case 1: 642 | //Decay 643 | setDecays(analogValues[i]); 644 | break; 645 | case 2: 646 | //Pitch 647 | setPitches(analogValues[i]); 648 | break; 649 | case 3: 650 | //Bit Crush 651 | crushBits = ((1023 - analogValues[i]) * 43.10); 652 | setfxSend(0,3,crushBits, 1); 653 | break; 654 | case 4: 655 | //Delay Time 656 | setfxSend(1,4,analogValues[i], 4); 657 | break; 658 | case 5: 659 | //Delay Feedback 660 | setfxSend(2,5,analogValues[i], 1023); 661 | break; 662 | case 6: 663 | //Global Filter, fxknob, param, value, scaler 664 | setfxSend(3,6,analogValues[i], 1); 665 | break; 666 | case 7: 667 | if(recSampMode){ 668 | //Input Volume 669 | extMixer.gain(0,analogValues[i]/511); 670 | extMixer.gain(1,analogValues[i]/511); 671 | }else{ 672 | //BPM / seq page 673 | if(!seqPlaying && !recAutMode){ 674 | ledSeqStep = constrain(analogValues[i] / 255.75,0,3); 675 | seqPage = seqPageArray[ledSeqStep]; 676 | pageChange = true; 677 | }else{ 678 | if(!slaveClock){ 679 | metroInt = map(analogValues[i], 0, 1023, 500, 75);; 680 | metronome.interval(metroInt); 681 | } 682 | } 683 | } 684 | break; 685 | case 8: 686 | if(recSampMode){ 687 | thresholdMin = analogValues[i] / 1023; 688 | }else{ 689 | thresholdMin = .5; 690 | //inst select 691 | instIndex = analogValues[i]/204; 692 | instIndex = constrain(instIndex, 0, 4); 693 | } 694 | break; 695 | } 696 | } 697 | analogValuesLag[i] = analogValues[i]; 698 | } 699 | //ext btns 700 | if(i < 2){ 701 | if ((abs(extBtnStatus[i] - prevExtBtnStatus[i]) > 0)){ 702 | if (extBtnStatus[i] == LOW && prevExtBtnStatus[i] == HIGH){ 703 | if(transportDown){ 704 | clearTimeStamp = millis(); 705 | menuTmStp = millis(); 706 | lightsOut(32); 707 | transportDown = false; 708 | lightInst(); 709 | }else{ 710 | if(i==0){ //rec btn 711 | clearTimeStamp = millis(); 712 | if(!seqPlaying){ 713 | //Sample Mode 714 | lightsOut(32); 715 | recSampMode = !recSampMode; 716 | seqPlaying = false; 717 | recAutMode = false; 718 | peakReached = false; 719 | 720 | if(recSampMode){ 721 | lightsOut(32); 722 | drumInstMixer.gain(2,0); 723 | drumInstMixer.gain(3,1); 724 | }else{ 725 | receivePulseCheck(); 726 | lightInst(); 727 | } 728 | Serial.print("Rec Sample Mode: "); 729 | Serial.println(recSampMode); 730 | }else{ 731 | //rec automation mode 732 | lightsOut(32); 733 | recAutMode = !recAutMode; 734 | lightInst(); 735 | if(!recAutMode){ 736 | peakReached = false; 737 | recArmed = false; 738 | } 739 | } 740 | }else if (i==1){//play btn 741 | menuTmStp = millis(); 742 | if(recSampMode){ 743 | recSampMode = false; 744 | lightsOut(32); 745 | receivePulseCheck(); 746 | lightInst(); 747 | }else{ 748 | seqPlaying = !seqPlaying; 749 | countSteps(); 750 | resetSeq(); 751 | } 752 | } 753 | } 754 | } 755 | prevExtBtnStatus[i] = extBtnStatus[i]; 756 | } 757 | if((extBtnStatus[0] == LOW && prevExtBtnStatus[0] == LOW) && (millis() - clearTimeStamp) > 1000){ 758 | clearEverything(); 759 | } 760 | if((extBtnStatus[1] == LOW && prevExtBtnStatus[1] == LOW) && (millis() - menuTmStp) > 1000){ 761 | lightsOut(32); 762 | transportDown = true; 763 | recSampMode = false; 764 | seqPlaying = false; 765 | } 766 | } 767 | } 768 | } 769 | for(int i=0; i<16; i++){ 770 | if(analogOpen[i] && abs(millis() - analogOpenTime[i]) > 300){ 771 | analogOpen[i] = false; 772 | } 773 | } 774 | 775 | //Pulse Sync 776 | if(!recSampMode){ 777 | if(peak1.available()){ 778 | extPeakVal = peak1.read(); 779 | peakDetect(extPeakVal); 780 | } 781 | } 782 | 783 | //Sequencer //&& !slaveClock 784 | if(seqPlaying && !slaveClock){ 785 | if (metronome.check() == 1) { 786 | seqStep++; 787 | ledSeqStep++; 788 | } 789 | } 790 | //Slave Double Time 791 | if(millis() >= (lastPulse + intervalTime/2) && receivePulse && doubleStep){ 792 | seqStep++; 793 | ledSeqStep++; 794 | doubleStep = false; 795 | } 796 | 797 | if((abs(seqStep - prevSeqStep) > 0) || pageChange){ 798 | //Serial.println(seqStep); 799 | if (seqStep > stepLimit && seqPlaying){ 800 | seqStep = 0; 801 | } 802 | if(ledSeqStep > 15){ 803 | ledSeqStep = 0; 804 | } 805 | //set seqPage 806 | if(seqPlaying){ 807 | if(seqStep < 16){ 808 | seqPage = 0; 809 | }else if(seqStep > 15 && seqStep < 32){ 810 | seqPage = 16; 811 | }else if(seqStep > 31 && seqStep < 48){ 812 | seqPage = 32; 813 | }else if(seqStep > 47){ 814 | seqPage = 48; 815 | } 816 | } 817 | if(!transportDown){ 818 | lightsOut(32); 819 | //background color for inst 820 | lightInst(); 821 | //seq step 822 | if(ledSeqStep == -1){ 823 | leds[0].setRGB(255,255,255); 824 | }else{ 825 | leds[ledSeqStep].setRGB(255,255,255); 826 | } 827 | } 828 | //play sounds 829 | if(seqPlaying){ 830 | if(!presetLoading){ 831 | if(trigs[0][seqStep]){ playKick(); } 832 | if(trigs[1][seqStep]){ playSnare(); } 833 | if(trigs[2][seqStep]){ playHh(); } 834 | if(trigs[3][seqStep]){ playTom(); } 835 | if(trigs[4][seqStep]){ playSample(); } 836 | } 837 | //pulse out 838 | if(sendPulse && seqStep % 2 == 0){ 839 | pulseOut.pulseWidth(1); 840 | pulseSentTime = millis(); 841 | pulseSent = true; 842 | } 843 | } 844 | 845 | prevSeqStep = seqStep; 846 | pageChange = false; 847 | } 848 | 849 | if(abs(millis() - pulseSentTime > 15)){ 850 | if(pulseSent){ 851 | pulseOut.pulseWidth(0); 852 | pulseSent = false; 853 | } 854 | } 855 | 856 | //blink 857 | blinkBrightness = 128+127*cos(2*PI/500*millis()); 858 | 859 | //transport down LEDS 860 | if(transportDown){ 861 | if(seqPlaying){ 862 | leds[0].setRGB(blinkBrightness,0,0); 863 | }else{ 864 | leds[0].setRGB(255,0,0); 865 | } 866 | //Sync 867 | if(syncNumber == 4){ 868 | leds[4].setRGB(blinkBrightness,0,0); 869 | }else{ 870 | leds[4].setRGB(255,0,0); 871 | } 872 | if(syncNumber == 5){ 873 | leds[5].setRGB(0,blinkBrightness,0); 874 | }else{ 875 | leds[5].setRGB(0,255,0); 876 | } 877 | if(syncNumber == 6){ 878 | leds[6].setRGB(0,0,blinkBrightness); 879 | }else{ 880 | leds[6].setRGB(0,0,255); 881 | } 882 | if(syncNumber == 7){ 883 | leds[7].setRGB(0,blinkBrightness,blinkBrightness); 884 | }else{ 885 | leds[7].setRGB(0,255,255); 886 | } 887 | //Load//Save 888 | for(int i=0; i<16; i++){ 889 | if(i > 7 && i < 12){ 890 | leds[i].setRGB(0,255,0); 891 | }else if(i > 11){ 892 | leds[i].setRGB(255,0,0); 893 | } 894 | leds[currentPreset+28].setRGB(0,0,255); 895 | } 896 | } 897 | if(!transportDown){ 898 | //Inst Colos 899 | if(abs(instIndex - prevInstIndex) > 0){ 900 | lightsOut(32); 901 | lightInst(); 902 | prevInstIndex = instIndex; 903 | } 904 | //Rec Blink 905 | if(recAutMode){ 906 | for(int i=0; i<16; i++){ 907 | if(i !=ledSeqStep){ 908 | leds[i].setRGB(0,blinkBrightness,0); 909 | } 910 | } 911 | } 912 | //light active step 913 | if(!recSampMode){ 914 | for(int i=0; i<16; i++){ 915 | if(trigs[instIndex][i+seqPage]){ 916 | leds[i+16].setRGB(0,0,255); 917 | } 918 | } 919 | } 920 | } 921 | 922 | //turn off slave clock 923 | if(abs(millis() - lastPulse > 2000) && slaveClock){ 924 | seqPlaying = false; 925 | slaveClock = false; 926 | intervalTime = 200; 927 | resetSeq(); 928 | } 929 | //turn off peak led 930 | if(abs(millis() - peakTimeStamp > 1000) && peakReached && recSampMode){ 931 | peakReached = false; 932 | peakTimeStamp = millis(); 933 | } 934 | 935 | firstRun = false; 936 | FastLED.show(); 937 | } 938 | void resetSeq(){ 939 | metronome.reset(); 940 | ledSeqStep = -1; 941 | seqStep = -1; 942 | seqPage = 0; 943 | } 944 | void countSteps(){ 945 | bool steps16 = false; 946 | bool steps32 = false; 947 | bool steps48 = false; 948 | bool steps64 = false; 949 | for(int i=0; i<5; i++){ 950 | for(int j=0; j<64; j++){ 951 | if(j<16){ 952 | if(trigs[i][j]) steps16 = true; 953 | } 954 | if(j > 15 && j < 32){ 955 | if(trigs[i][j]) steps32 = true; 956 | } 957 | if(j > 31 && j < 48){ 958 | if(trigs[i][j]) steps48 = true; 959 | } 960 | if(j > 47){ 961 | if(trigs[i][j]) steps64 = true; 962 | } 963 | } 964 | } 965 | if(steps16) stepLimit = 15; 966 | if(steps32) stepLimit = 31; 967 | if(steps48) stepLimit = 47; 968 | if(steps64) stepLimit = 63; 969 | Serial.println(stepLimit); 970 | } 971 | void syncSettings(int syncCase){ 972 | lightsOut(32); 973 | seqPlaying = false; 974 | resetSeq(); 975 | if(syncCase == 4){ 976 | for(int i=0; i<16; i++){ 977 | leds[i].setRGB(0,0,255); 978 | leds[i+16].setRGB(0,0,255); 979 | FastLED.show(); 980 | delay(50); 981 | } 982 | sendPulse = true; 983 | receivePulse = false; 984 | }else if (syncCase == 5){ 985 | for(int i=15; i>0; i--){ 986 | leds[i].setRGB(255,0,0); 987 | leds[i+16].setRGB(255,0,0); 988 | FastLED.show(); 989 | delay(50); 990 | } 991 | receivePulse = true; 992 | sendPulse = false; 993 | }else if(syncCase == 6){ 994 | for(int i=0; i<16; i++){ 995 | leds[i].setRGB(0,0,255); 996 | leds[i+16].setRGB(0,0,255); 997 | FastLED.show(); 998 | delay(25); 999 | } 1000 | lightsOut(32); 1001 | for(int i=15; i>0; i--){ 1002 | leds[i].setRGB(255,0,0); 1003 | leds[i+16].setRGB(255,0,0); 1004 | FastLED.show(); 1005 | delay(25); 1006 | } 1007 | sendPulse = true; 1008 | receivePulse = true; 1009 | }else{ 1010 | for(int i=0; i<32; i++){ 1011 | leds[i].setRGB(0,0,255); 1012 | FastLED.show(); 1013 | } 1014 | delay(500); 1015 | sendPulse = false; 1016 | receivePulse = false; 1017 | } 1018 | lightsOut(32); 1019 | sendPulseCheck(); 1020 | receivePulseCheck(); 1021 | //lightInst(); 1022 | //transportDown = false; 1023 | syncNumber = syncCase; 1024 | } 1025 | void receivePulseCheck(){ 1026 | if(receivePulse){ 1027 | drumInstMixer.gain(2,1); 1028 | drumInstMixer.gain(3,0); 1029 | extMixer.gain(0,0); 1030 | extMixer.gain(1,1); 1031 | }else{ 1032 | drumInstMixer.gain(2,0); 1033 | drumInstMixer.gain(3,1); 1034 | extMixer.gain(0,1); 1035 | extMixer.gain(1,1); 1036 | } 1037 | } 1038 | void sendPulseCheck(){ 1039 | if(sendPulse){ 1040 | pulseOutMixer.gain(0,0); 1041 | pulseOutMixer.gain(1,.75); 1042 | }else{ 1043 | pulseOutMixer.gain(0,1); 1044 | pulseOutMixer.gain(1,0); 1045 | } 1046 | } 1047 | 1048 | void clearEverything(){ 1049 | Serial.println("clear"); 1050 | lightsOut(32); 1051 | for(int i=0; i<5; i++){ 1052 | for(int j=0; j<64; j++){ 1053 | trigs[i][j] = false; 1054 | for(int w=0; w<7; w++){ 1055 | params[i][j][w] = 0; 1056 | } 1057 | } 1058 | } 1059 | stepLimit = 15; 1060 | recAutMode = false; 1061 | recSampMode = false; 1062 | clearTimeStamp = millis(); 1063 | lightInst(); 1064 | resetSeq(); 1065 | } 1066 | 1067 | void lightsOut(int number){ 1068 | for (int i = 0; i < number; ++i){ 1069 | leds[i].setRGB(0,0,0); 1070 | } 1071 | } 1072 | void lightInst(){ 1073 | for(int i=0; i<16; i++){ 1074 | if(i%4){ 1075 | leds[i].setRGB((colorArray[instIndex][0])*.2,(colorArray[instIndex][1])*.2,(colorArray[instIndex][2])*.2); 1076 | }else{ 1077 | leds[i].setRGB(colorArray[instIndex][0],colorArray[instIndex][1],colorArray[instIndex][2]); 1078 | } 1079 | } 1080 | if(ledSeqStep == -1){ 1081 | leds[0].setRGB(255,255,255); 1082 | }else{ 1083 | leds[ledSeqStep].setRGB(255,255,255); 1084 | } 1085 | } 1086 | 1087 | void setMuxPin(int channel){ 1088 | int controlPin[] = {s0, s1, s2, s3}; 1089 | 1090 | int muxChannel[16][4]={ 1091 | {0,0,0,0}, //channel 0 1092 | {1,0,0,0}, //channel 1 1093 | {0,1,0,0}, //channel 2 1094 | {1,1,0,0}, //channel 3 1095 | {0,0,1,0}, //channel 4 1096 | {1,0,1,0}, //channel 5 1097 | {0,1,1,0}, //channel 6 1098 | {1,1,1,0}, //channel 7 1099 | {0,0,0,1}, //channel 8 1100 | {1,0,0,1}, //channel 9 1101 | {0,1,0,1}, //channel 10 1102 | {1,1,0,1}, //channel 11 1103 | {0,0,1,1}, //channel 12 1104 | {1,0,1,1}, //channel 13 1105 | {0,1,1,1}, //channel 14 1106 | {1,1,1,1}, //channel 15 1107 | }; 1108 | 1109 | //loop through the 4 sig 1110 | for(int i = 0; i < 4; i ++){ 1111 | digitalWrite(controlPin[i], muxChannel[channel][i]); 1112 | } 1113 | } 1114 | void startRecording(int wavIndex) { 1115 | 1116 | Serial.print("Start Recording:"); 1117 | Serial.println(wavSamples[wavIndex]); 1118 | sampleSlot[wavIndex] = true; 1119 | 1120 | frec = SD.open(wavSamples[wavIndex], FILE_WRITE); 1121 | if (frec) { 1122 | queue1.begin(); 1123 | } 1124 | 1125 | } 1126 | void continueRecording() { 1127 | if (queue1.available() >= 2) { 1128 | byte buffer[512]; 1129 | // Fetch 2 blocks from the audio library and copy 1130 | // into a 512 byte buffer. The Arduino SD library 1131 | // is most efficient when full 512 byte sector size 1132 | // writes are used. 1133 | memcpy(buffer, queue1.readBuffer(), 256); 1134 | queue1.freeBuffer(); 1135 | memcpy(buffer+256, queue1.readBuffer(), 256); 1136 | queue1.freeBuffer(); 1137 | // write all 512 bytes to the SD card 1138 | frec.write(buffer, 512); 1139 | } 1140 | } 1141 | void stopRecording() { 1142 | queue1.end(); 1143 | if(recording){ 1144 | while (queue1.available() > 0) { 1145 | frec.write((byte*)queue1.readBuffer(), 256); 1146 | queue1.freeBuffer(); 1147 | } 1148 | frec.close(); 1149 | } 1150 | recording = false; 1151 | Serial.println("End Recording:"); 1152 | } 1153 | 1154 | void peakDetect(float voltage) 1155 | { 1156 | // "static" variables keep their numbers between each run of this function 1157 | static int state; // 0=idle, 1=looking for peak, 2=ignore aftershocks 1158 | static int peak; // remember the highest reading 1159 | static elapsedMillis msec; // timer to end states 1 and 2 1160 | 1161 | switch (state) { 1162 | // IDLE state: wait for any reading is above threshold. Do not set 1163 | // the threshold too low. You don't want to be too sensitive to slight 1164 | // vibration. 1165 | case 0: 1166 | if (voltage > thresholdMin) { 1167 | peak = voltage; 1168 | msec = 0; 1169 | state = 1; 1170 | } 1171 | return; 1172 | 1173 | // Peak Tracking state: capture largest reading 1174 | case 1: 1175 | if (voltage > peak) { 1176 | peak = voltage; 1177 | } 1178 | if (msec >= peakTrackMillis) { 1179 | peakReached = true; 1180 | if(recSampMode){ 1181 | peakTimeStamp = millis(); 1182 | } 1183 | 1184 | if(!recSampMode && receivePulse){ 1185 | if(slaveClock){ 1186 | countSteps(); 1187 | intervalTime = millis() - lastPulse; 1188 | } 1189 | lastPulse = millis(); 1190 | slaveClock = true; 1191 | seqPlaying = true; 1192 | doubleStep = true; 1193 | seqStep++; 1194 | ledSeqStep++; 1195 | } 1196 | 1197 | msec = 0; 1198 | state = 2; 1199 | } 1200 | return; 1201 | 1202 | // Ignore Aftershock state: wait for things to be quiet again. 1203 | default: 1204 | if (voltage > thresholdMin) { 1205 | msec = 0; // keep resetting timer if above threshold 1206 | } 1207 | else if (msec > aftershockMillis) { 1208 | state = 0; // go back to idle when 1209 | } 1210 | } 1211 | } 1212 | void RealTimeSystem(byte realtimebyte) { 1213 | if(realtimebyte == START || realtimebyte == CONTINUE) { 1214 | //Serial.println("start"); 1215 | counter = 0; 1216 | slaveClock = false; 1217 | seqPlaying = false; 1218 | resetSeq(); 1219 | } 1220 | 1221 | if(realtimebyte == 248) { 1222 | counter++; 1223 | if(counter == 6) { 1224 | counter = 0; 1225 | } 1226 | if(counter == 1){ 1227 | lastPulse = millis(); 1228 | slaveClock = true; 1229 | seqPlaying = true; 1230 | seqStep++; 1231 | ledSeqStep++; 1232 | } 1233 | } 1234 | if(realtimebyte == STOP) { 1235 | //Serial.println("stop"); 1236 | slaveClock = false;; 1237 | seqPlaying = false; 1238 | resetSeq(); 1239 | } 1240 | } 1241 | 1242 | void loadPreset(int number){ 1243 | playSdRaw1.stop(); 1244 | presetLoading = true; 1245 | AudioNoInterrupts(); 1246 | //seqPlaying = false; 1247 | String currentPreset = fileNames[number]; 1248 | 1249 | myFile = SD.open(currentPreset.c_str()); 1250 | 1251 | if (myFile) { 1252 | for(int i=0; i<5; i++){ 1253 | for(int s=0; s<64; s++){ 1254 | inputOne = myFile.parseFloat(); 1255 | trigs[i][s] = inputOne; 1256 | for(int p=0; p<7; p++){ 1257 | inputTwo = myFile.parseFloat(); 1258 | params[i][s][p] = inputTwo; 1259 | } 1260 | } 1261 | } 1262 | // close the file: 1263 | myFile.close(); 1264 | countSteps(); 1265 | } else { 1266 | // if the file didn't open, print an error: 1267 | Serial.println("error opening file"); 1268 | } 1269 | AudioInterrupts(); 1270 | presetLoading = false; 1271 | } 1272 | 1273 | void savePreset(int number){ 1274 | String currentPreset = fileNames[number]; 1275 | //Remove File 1276 | if (SD.exists(currentPreset.c_str())) { 1277 | Serial.println("remove the file"); 1278 | SD.remove(currentPreset.c_str()); 1279 | } 1280 | //open File 1281 | myFile = SD.open(currentPreset.c_str(), FILE_WRITE); 1282 | //if the file opened okay, write to it: 1283 | 1284 | // bool trigs[5][64]; 1285 | // float params[5][64][7]; 1286 | if (myFile) { 1287 | for(int i=0; i<5; i++){ 1288 | for(int s=0; s<64; s++){ 1289 | myFile.println(trigs[i][s]); 1290 | // Serial.print("trigs: "); 1291 | // Serial.print(i); 1292 | // Serial.print(" : "); 1293 | // Serial.print(s); 1294 | // Serial.print(" : "); 1295 | // Serial.println(trigs[i][s]); 1296 | for(int p=0; p<7; p++){ 1297 | myFile.println(params[i][s][p]); 1298 | // Serial.print("params : "); 1299 | // Serial.print(i); 1300 | // Serial.print(" : "); 1301 | // Serial.print(s); 1302 | // Serial.print(" : "); 1303 | // Serial.print(p); 1304 | // Serial.print(" : "); 1305 | // Serial.println(params[i][s][p]); 1306 | } 1307 | } 1308 | } 1309 | // close the file: 1310 | myFile.close(); 1311 | Serial.print("wrote to file"); 1312 | } else { 1313 | // if the file didn't open, print an error: 1314 | Serial.println("error opening file"); 1315 | } 1316 | } 1317 | -------------------------------------------------------------------------------- /Cirrus/Cirrus.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // GUItool: begin automatically generated code 8 | AudioSynthWaveform lfoPitch2; //xy=92,363 9 | AudioSynthWaveform lfoPitch4; //xy=92,845 10 | AudioSynthWaveform lfoPitch6; //xy=92,1343 11 | AudioSynthWaveform lfoPitch8; //xy=92,1825 12 | AudioSynthWaveform lfoPitch1; //xy=138,129 13 | AudioSynthWaveform lfoPitch3; //xy=138,611 14 | AudioSynthWaveform lfoPitch5; //xy=138,1109 15 | AudioSynthWaveform lfoPitch7; //xy=138,1592 16 | AudioSynthWaveformDc dc2; //xy=258,374 17 | AudioSynthWaveformDc dc4; //xy=258,857 18 | AudioSynthWaveformDc dc6; //xy=258,1355 19 | AudioSynthWaveformDc dc8; //xy=258,1837 20 | AudioSynthWaveformDc dc1; //xy=304,141 21 | AudioSynthWaveformDc dc3; //xy=304,623 22 | AudioSynthWaveformDc dc5; //xy=304,1121 23 | AudioSynthWaveformDc dc7; //xy=304,1604 24 | AudioSynthWaveform tri2; //xy=315,334 25 | AudioSynthWaveformModulated sawB2; //xy=316,297 26 | AudioSynthWaveform tri4; //xy=315,817 27 | AudioSynthWaveformModulated sawA2; //xy=318,264 28 | AudioSynthWaveformModulated sawB4; //xy=316,779 29 | AudioSynthWaveform tri6; //xy=315,1315 30 | AudioSynthWaveformModulated sawA4; //xy=318,746 31 | AudioSynthWaveformModulated sawB6; //xy=316,1277 32 | AudioSynthWaveform tri8; //xy=315,1797 33 | AudioSynthWaveformModulated sawA6; //xy=318,1244 34 | AudioSynthWaveformModulated sawB8; //xy=316,1760 35 | AudioSynthWaveformModulated sawA8; //xy=318,1726 36 | AudioSynthWaveformModulated modu2; //xy=324,444 37 | AudioSynthWaveformModulated modu4; //xy=324,926 38 | AudioSynthWaveformModulated modu6; //xy=324,1424 39 | AudioSynthWaveformModulated modu8; //xy=324,1907 40 | AudioSynthWaveformModulated sawB1; //xy=362,64 41 | AudioSynthWaveform tri1; //xy=362,101 42 | AudioSynthWaveformModulated sawB3; //xy=362,546 43 | AudioSynthWaveform tri3; //xy=362,583 44 | AudioSynthWaveformModulated sawA1; //xy=365,30 45 | AudioSynthWaveformModulated sawB5; //xy=362,1044 46 | AudioSynthWaveform tri5; //xy=362,1081 47 | AudioSynthWaveformModulated sawA3; //xy=365,513 48 | AudioSynthWaveformModulated sawB7; //xy=362,1526 49 | AudioSynthWaveform tri7; //xy=362,1564 50 | AudioSynthWaveformModulated sawA5; //xy=365,1011 51 | AudioSynthWaveformModulated sawA7; //xy=365,1493 52 | AudioSynthWaveformModulated modu1; //xy=371,210 53 | AudioSynthWaveformModulated modu3; //xy=371,693 54 | AudioSynthWaveformModulated modu5; //xy=371,1191 55 | AudioSynthWaveformModulated modu7; //xy=371,1673 56 | AudioEffectEnvelope filEnv2; //xy=384,382 57 | AudioEffectEnvelope filEnv4; //xy=384,864 58 | AudioEffectEnvelope filEnv6; //xy=384,1362 59 | AudioEffectEnvelope filEnv8; //xy=384,1845 60 | AudioEffectEnvelope filEnv1; //xy=430,149 61 | AudioEffectEnvelope filEnv3; //xy=430,631 62 | AudioEffectEnvelope filEnv5; //xy=430,1129 63 | AudioEffectEnvelope filEnv7; //xy=430,1611 64 | AudioMixer4 fmixer2; //xy=449,283 65 | AudioMixer4 fmixer4; //xy=449,765 66 | AudioMixer4 fmixer6; //xy=449,1263 67 | AudioMixer4 fmixer8; //xy=449,1746 68 | AudioEffectMultiply mult2; //xy=475,442 69 | AudioEffectMultiply mult4; //xy=475,924 70 | AudioEffectMultiply mult6; //xy=475,1422 71 | AudioEffectMultiply mult8; //xy=475,1905 72 | AudioMixer4 fmixer1; //xy=495,50 73 | AudioMixer4 fmixer3; //xy=495,532 74 | AudioMixer4 fmixer5; //xy=495,1030 75 | AudioMixer4 fmixer7; //xy=495,1512 76 | AudioEffectMultiply mult1; //xy=522,209 77 | AudioEffectMultiply mult3; //xy=522,691 78 | AudioEffectMultiply mult5; //xy=522,1189 79 | AudioEffectMultiply mult7; //xy=522,1671 80 | AudioFilterStateVariable filter2; //xy=599,333 81 | AudioFilterStateVariable filter4; //xy=599,816 82 | AudioFilterStateVariable filter6; //xy=599,1314 83 | AudioFilterStateVariable filter8; //xy=599,1796 84 | AudioSynthWaveformSineModulated carA2; //xy=613,448 85 | AudioSynthWaveformSineModulated carA4; //xy=613,931 86 | AudioSynthWaveformSineModulated carA6; //xy=613,1429 87 | AudioSynthWaveformSineModulated carA8; //xy=613,1911 88 | AudioFilterStateVariable filter1; //xy=646,100 89 | AudioFilterStateVariable filter3; //xy=646,582 90 | AudioFilterStateVariable filter5; //xy=646,1080 91 | AudioFilterStateVariable filter7; //xy=646,1563 92 | AudioSynthWaveformSineModulated carA1; //xy=659,215 93 | AudioSynthWaveformSineModulated carA3; //xy=659,697 94 | AudioSynthWaveformSineModulated carA5; //xy=659,1195 95 | AudioSynthWaveformSineModulated carA7; //xy=659,1678 96 | AudioMixer4 voiceMixer2; //xy=899,405 97 | AudioMixer4 voiceMixer4; //xy=899,887 98 | AudioMixer4 voiceMixer6; //xy=899,1385 99 | AudioMixer4 voiceMixer8; //xy=899,1868 100 | AudioMixer4 voiceMixer1; //xy=945,172 101 | AudioMixer4 voiceMixer3; //xy=945,654 102 | AudioMixer4 voiceMixer5; //xy=945,1152 103 | AudioMixer4 voiceMixer7; //xy=945,1634 104 | AudioEffectEnvelope envelope2; //xy=1074,406 105 | AudioEffectEnvelope envelope4; //xy=1074,889 106 | AudioEffectEnvelope envelope6; //xy=1074,1387 107 | AudioEffectEnvelope envelope8; //xy=1074,1869 108 | AudioEffectEnvelope envelope1; //xy=1120,173 109 | AudioEffectEnvelope envelope3; //xy=1120,655 110 | AudioEffectEnvelope envelope5; //xy=1120,1153 111 | AudioEffectEnvelope envelope7; //xy=1120,1636 112 | AudioAnalyzePeak vPeak2; //xy=1221,344 113 | AudioAnalyzePeak vPeak4; //xy=1221,826 114 | AudioAnalyzePeak vPeak6; //xy=1221,1324 115 | AudioAnalyzePeak vPeak8; //xy=1221,1807 116 | AudioAnalyzePeak vPeak1; //xy=1268,111 117 | AudioAnalyzePeak vPeak3; //xy=1268,593 118 | AudioAnalyzePeak vPeak5; //xy=1268,1091 119 | AudioAnalyzePeak vPeak7; //xy=1268,1573 120 | AudioMixer4 preMix2; //xy=1682,814 121 | AudioMixer4 preMix1; //xy=1715,520 122 | AudioMixer4 finalMixer; //xy=1848,595 123 | AudioEffectFreeverb freeverb1; //xy=1923,665 124 | AudioMixer4 verbMixer; //xy=2011,599 125 | AudioOutputAnalogStereo dacs1; //xy=2144,562 126 | AudioConnection patchCord1(lfoPitch2, 0, modu2, 0); 127 | AudioConnection patchCord2(lfoPitch2, 0, sawA2, 0); 128 | AudioConnection patchCord3(lfoPitch4, 0, modu4, 0); 129 | AudioConnection patchCord4(lfoPitch4, 0, sawA4, 0); 130 | AudioConnection patchCord5(lfoPitch6, 0, modu6, 0); 131 | AudioConnection patchCord6(lfoPitch6, 0, sawA6, 0); 132 | AudioConnection patchCord7(lfoPitch8, 0, modu8, 0); 133 | AudioConnection patchCord8(lfoPitch8, 0, sawA8, 0); 134 | AudioConnection patchCord9(lfoPitch1, 0, modu1, 0); 135 | AudioConnection patchCord10(lfoPitch1, 0, sawA1, 0); 136 | AudioConnection patchCord11(lfoPitch3, 0, modu3, 0); 137 | AudioConnection patchCord12(lfoPitch3, 0, sawA3, 0); 138 | AudioConnection patchCord13(lfoPitch5, 0, modu5, 0); 139 | AudioConnection patchCord14(lfoPitch5, 0, sawA5, 0); 140 | AudioConnection patchCord15(lfoPitch7, 0, modu7, 0); 141 | AudioConnection patchCord16(lfoPitch7, 0, sawA7, 0); 142 | AudioConnection patchCord17(dc2, filEnv2); 143 | AudioConnection patchCord18(dc4, filEnv4); 144 | AudioConnection patchCord19(dc6, filEnv6); 145 | AudioConnection patchCord20(dc8, filEnv8); 146 | AudioConnection patchCord21(dc1, filEnv1); 147 | AudioConnection patchCord22(dc3, filEnv3); 148 | AudioConnection patchCord23(dc5, filEnv5); 149 | AudioConnection patchCord24(dc7, filEnv7); 150 | AudioConnection patchCord25(tri2, 0, fmixer2, 2); 151 | AudioConnection patchCord26(sawB2, 0, fmixer2, 1); 152 | AudioConnection patchCord27(tri4, 0, fmixer4, 2); 153 | AudioConnection patchCord28(sawA2, 0, fmixer2, 0); 154 | AudioConnection patchCord29(sawB4, 0, fmixer4, 1); 155 | AudioConnection patchCord30(tri6, 0, fmixer6, 2); 156 | AudioConnection patchCord31(sawA4, 0, fmixer4, 0); 157 | AudioConnection patchCord32(sawB6, 0, fmixer6, 1); 158 | AudioConnection patchCord33(tri8, 0, fmixer8, 2); 159 | AudioConnection patchCord34(sawA6, 0, fmixer6, 0); 160 | AudioConnection patchCord35(sawB8, 0, fmixer8, 1); 161 | AudioConnection patchCord36(sawA8, 0, fmixer8, 0); 162 | AudioConnection patchCord37(modu2, 0, mult2, 1); 163 | AudioConnection patchCord38(modu4, 0, mult4, 1); 164 | AudioConnection patchCord39(modu6, 0, mult6, 1); 165 | AudioConnection patchCord40(modu8, 0, mult8, 1); 166 | AudioConnection patchCord41(sawB1, 0, fmixer1, 1); 167 | AudioConnection patchCord42(tri1, 0, fmixer1, 2); 168 | AudioConnection patchCord43(sawB3, 0, fmixer3, 1); 169 | AudioConnection patchCord44(tri3, 0, fmixer3, 2); 170 | AudioConnection patchCord45(sawA1, 0, fmixer1, 0); 171 | AudioConnection patchCord46(sawB5, 0, fmixer5, 1); 172 | AudioConnection patchCord47(tri5, 0, fmixer5, 2); 173 | AudioConnection patchCord48(sawA3, 0, fmixer3, 0); 174 | AudioConnection patchCord49(sawB7, 0, fmixer7, 1); 175 | AudioConnection patchCord50(tri7, 0, fmixer7, 2); 176 | AudioConnection patchCord51(sawA5, 0, fmixer5, 0); 177 | AudioConnection patchCord52(sawA7, 0, fmixer7, 0); 178 | AudioConnection patchCord53(modu1, 0, mult1, 1); 179 | AudioConnection patchCord54(modu3, 0, mult3, 1); 180 | AudioConnection patchCord55(modu5, 0, mult5, 1); 181 | AudioConnection patchCord56(modu7, 0, mult7, 1); 182 | AudioConnection patchCord57(filEnv2, 0, filter2, 1); 183 | AudioConnection patchCord58(filEnv2, 0, mult2, 0); 184 | AudioConnection patchCord59(filEnv4, 0, filter4, 1); 185 | AudioConnection patchCord60(filEnv4, 0, mult4, 0); 186 | AudioConnection patchCord61(filEnv6, 0, filter6, 1); 187 | AudioConnection patchCord62(filEnv6, 0, mult6, 0); 188 | AudioConnection patchCord63(filEnv8, 0, filter8, 1); 189 | AudioConnection patchCord64(filEnv8, 0, mult8, 0); 190 | AudioConnection patchCord65(filEnv1, 0, filter1, 1); 191 | AudioConnection patchCord66(filEnv1, 0, mult1, 0); 192 | AudioConnection patchCord67(filEnv3, 0, filter3, 1); 193 | AudioConnection patchCord68(filEnv3, 0, mult3, 0); 194 | AudioConnection patchCord69(filEnv5, 0, filter5, 1); 195 | AudioConnection patchCord70(filEnv5, 0, mult5, 0); 196 | AudioConnection patchCord71(filEnv7, 0, filter7, 1); 197 | AudioConnection patchCord72(filEnv7, 0, mult7, 0); 198 | AudioConnection patchCord73(fmixer2, 0, filter2, 0); 199 | AudioConnection patchCord74(fmixer4, 0, filter4, 0); 200 | AudioConnection patchCord75(fmixer6, 0, filter6, 0); 201 | AudioConnection patchCord76(fmixer8, 0, filter8, 0); 202 | AudioConnection patchCord77(mult2, carA2); 203 | AudioConnection patchCord78(mult4, carA4); 204 | AudioConnection patchCord79(mult6, carA6); 205 | AudioConnection patchCord80(mult8, carA8); 206 | AudioConnection patchCord81(fmixer1, 0, filter1, 0); 207 | AudioConnection patchCord82(fmixer3, 0, filter3, 0); 208 | AudioConnection patchCord83(fmixer5, 0, filter5, 0); 209 | AudioConnection patchCord84(fmixer7, 0, filter7, 0); 210 | AudioConnection patchCord85(mult1, carA1); 211 | AudioConnection patchCord86(mult3, carA3); 212 | AudioConnection patchCord87(mult5, carA5); 213 | AudioConnection patchCord88(mult7, carA7); 214 | AudioConnection patchCord89(filter2, 0, voiceMixer2, 0); 215 | AudioConnection patchCord90(filter4, 0, voiceMixer4, 0); 216 | AudioConnection patchCord91(filter6, 0, voiceMixer6, 0); 217 | AudioConnection patchCord92(filter8, 0, voiceMixer8, 0); 218 | AudioConnection patchCord93(carA2, 0, voiceMixer2, 2); 219 | AudioConnection patchCord94(carA4, 0, voiceMixer4, 2); 220 | AudioConnection patchCord95(carA6, 0, voiceMixer6, 2); 221 | AudioConnection patchCord96(carA8, 0, voiceMixer8, 2); 222 | AudioConnection patchCord97(filter1, 0, voiceMixer1, 0); 223 | AudioConnection patchCord98(filter3, 0, voiceMixer3, 0); 224 | AudioConnection patchCord99(filter5, 0, voiceMixer5, 0); 225 | AudioConnection patchCord100(filter7, 0, voiceMixer7, 0); 226 | AudioConnection patchCord101(carA1, 0, voiceMixer1, 2); 227 | AudioConnection patchCord102(carA3, 0, voiceMixer3, 2); 228 | AudioConnection patchCord103(carA5, 0, voiceMixer5, 2); 229 | AudioConnection patchCord104(carA7, 0, voiceMixer7, 2); 230 | AudioConnection patchCord105(voiceMixer2, envelope2); 231 | AudioConnection patchCord106(voiceMixer4, envelope4); 232 | AudioConnection patchCord107(voiceMixer6, envelope6); 233 | AudioConnection patchCord108(voiceMixer8, envelope8); 234 | AudioConnection patchCord109(voiceMixer1, envelope1); 235 | AudioConnection patchCord110(voiceMixer3, envelope3); 236 | AudioConnection patchCord111(voiceMixer5, envelope5); 237 | AudioConnection patchCord112(voiceMixer7, envelope7); 238 | AudioConnection patchCord113(envelope2, vPeak2); 239 | AudioConnection patchCord114(envelope2, 0, preMix1, 1); 240 | AudioConnection patchCord115(envelope4, vPeak4); 241 | AudioConnection patchCord116(envelope4, 0, preMix1, 3); 242 | AudioConnection patchCord117(envelope6, vPeak6); 243 | AudioConnection patchCord118(envelope6, 0, preMix2, 1); 244 | AudioConnection patchCord119(envelope8, vPeak8); 245 | AudioConnection patchCord120(envelope8, 0, preMix2, 3); 246 | AudioConnection patchCord121(envelope1, 0, preMix1, 0); 247 | AudioConnection patchCord122(envelope1, vPeak1); 248 | AudioConnection patchCord123(envelope3, vPeak3); 249 | AudioConnection patchCord124(envelope3, 0, preMix1, 2); 250 | AudioConnection patchCord125(envelope5, vPeak5); 251 | AudioConnection patchCord126(envelope5, 0, preMix2, 0); 252 | AudioConnection patchCord127(envelope7, vPeak7); 253 | AudioConnection patchCord128(envelope7, 0, preMix2, 2); 254 | AudioConnection patchCord129(preMix2, 0, finalMixer, 1); 255 | AudioConnection patchCord130(preMix1, 0, finalMixer, 0); 256 | AudioConnection patchCord131(finalMixer, 0, verbMixer, 0); 257 | AudioConnection patchCord132(finalMixer, freeverb1); 258 | AudioConnection patchCord133(freeverb1, 0, verbMixer, 1); 259 | AudioConnection patchCord134(verbMixer, 0, dacs1, 0); 260 | AudioConnection patchCord135(verbMixer, 0, dacs1, 1); 261 | // GUItool: end automatically generated code 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | /////////////////////////////////////////////////////////////////////////////////////// 300 | //======================================PCB_PINS=========================================// 301 | //Teensy 3.6 usb midi 302 | //Touch === 30,29,23,22,19,18,1,0 303 | //Knobs === A12,A13,A6,A7,A14,A15,A16,A17,A18,A19,A20,A10 304 | //Switch == 25,13,14 305 | //LEDS ==== 28 306 | //Encoder = 26,27 307 | //CLK ===== 16,17 308 | 309 | #include 310 | #include 311 | #define FASTLED_ALLOW_INTERRUPTS 0 312 | #include 313 | 314 | //leds 315 | #define DATA_PIN 28 316 | #define NUM_LEDS 8 317 | #define COLOR_ORDER RGB 318 | CRGB leds[NUM_LEDS]; 319 | 320 | int temp; 321 | //Encoder 322 | int encoderPin1 = 26; 323 | int encoderPin2 = 27; 324 | volatile int lastEncoded = 0; 325 | volatile long encoderValue = 0; 326 | int scaledEncVal; 327 | int prevScaledEncVal; 328 | int encoded; 329 | 330 | int ClkOutPin = 16; 331 | int ClkInPin = 17; 332 | float voices[8]; 333 | bool voiceUsed[8]; 334 | int voiceNum; 335 | 336 | 337 | Bounce swBouncers[4] = { 338 | Bounce(25,100), 339 | Bounce(13,100), 340 | Bounce(14,100), 341 | Bounce(ClkInPin,15), 342 | 343 | }; 344 | int swPins[3] = {25,13,14}; 345 | 346 | 347 | float analogValues[12]; 348 | float analogValuesLag[12]; 349 | bool knobLocks[12]; 350 | int analogPins[12] = {A12,A13,A6,A7,A14,A15,A16,A17,A18,A19,A20,A10}; 351 | int knobThresh = 8; 352 | 353 | bool noteTouched[8] = {false}; 354 | int noteTouchPins[8] = {30,29,23,22,19,18,1,0}; 355 | float envTrig[8]; 356 | float currentYPos[8]; 357 | float scaledYpos[8]; 358 | float prevScaledYpos[8]; 359 | bool allOff[8] = {false}; 360 | 361 | //Synth Paramaters 362 | bool unisonMode; 363 | bool glide; 364 | bool yToMix; 365 | bool yToFilter; 366 | bool yTolfoOneSpeed; 367 | bool ytoLfoOneAmt; 368 | bool yTofilEnvAttack; 369 | bool ytofilEnvDecay; 370 | float glideSpeed = 1.1; 371 | 372 | float lfo2PeakVals[8]; 373 | float lfo2PeakMult; 374 | 375 | float verbMix; 376 | float lfoOneAmt; 377 | float lfoOneFreq; 378 | bool superLfo; 379 | int superIndex; 380 | float filEnvDecay; 381 | float filEnvAttack; 382 | float voiceMixerVal[8]; 383 | 384 | 385 | int octIndex; 386 | int fmIndex; 387 | float filterMulti; 388 | float fmMulti; 389 | float detuneAmt[8] = {1,1,1,1,1,1,1,1}; 390 | 391 | 392 | float voicePeaks[8]; 393 | 394 | int lfoTimeMathArray[5] = {250, 500, 1000, 2000, 4000}; 395 | int lfoIndex; 396 | bool loopEnv; 397 | 398 | float fmRatioArray[9] = { 399 | .25,.5,.75,1,2,4,8,16,20 400 | }; 401 | float octArray[5] = { 402 | .25,.5,1,2,4 403 | }; 404 | bool firstRun = true; 405 | 406 | 407 | int scale; 408 | float noteFrequencies[8][8] = { 409 | //Amin 410 | {220.00,246.94,261.63,293.66,329.63,349.23,392.00,440.00}, 411 | //Bmin 412 | {246.94,277.18,293.66,329.63,369.99,392.00,440.00,493.88}, 413 | //Cmin 414 | {261.63,293.66,311.13,349.23,392.00,415.30,466.16,523.25}, 415 | //Dmin 416 | {293.66,329.63,349.23,392.00,440.00,466.16,523.25,587.33}, 417 | //Emin 418 | {329.63,369.99,392.00,440.00,493.88,523.25,587.33,659.25}, 419 | //Fmin 420 | {349.23,392.00,415.30,466.16,523.25,554.37,622.25,698.46}, 421 | //Gmin 422 | {392.00,440.00,466.16,523.25,587.33,622.25,698.46,783.99}, 423 | //Chrom 424 | {220.00,233.08,246.94,261.63,277.18,293.66,311.13,329.63}, 425 | }; 426 | float newFreq = 220; 427 | float oldFreq = 220; 428 | float colorArray[8][3]{ 429 | {255, 119, 0}, 430 | {255,238,0}, 431 | {101,255,0}, 432 | {0,255,106}, 433 | {0,199,255}, 434 | {8,0,255}, 435 | {238,0,255}, 436 | {255,0,0}, 437 | }; 438 | int blinkBrightness; 439 | int blinkControl; 440 | bool lightStepZero; 441 | 442 | float frequency[8]; 443 | float noTouchVal[8]; 444 | 445 | float onAvgVals[8][20]; 446 | int onAvgCnt; 447 | float onAvgerages[8]; 448 | 449 | //PRESETS 450 | int paramVals[24]; 451 | int presetNum; 452 | bool presetLoaded; 453 | bool presetLoading; 454 | bool savePresetCheck; 455 | 456 | //Sequencer 457 | bool slaveFlag; 458 | unsigned long pulseInStamp; 459 | bool doubleStep; 460 | unsigned long doubleInterval = 200; 461 | bool pulseInR; 462 | unsigned long pulseSentTime; 463 | bool tapTempoFlag = false; 464 | int tapTempoAmount; 465 | unsigned long tapTempTimeStamp[4]; 466 | //slave MIDI 467 | byte counter; 468 | byte CLOCK = 248; 469 | byte START = 250; 470 | byte CONTINUE = 251; 471 | byte STOP = 252; 472 | 473 | // [step] [note] extra 474 | int seqNotes[32][9]; 475 | // [step] [knob] 476 | int seqParams[32][14]; 477 | // [step] [yPos] 478 | float seqYpos[32][8]; 479 | 480 | 481 | float metroInterval = 300; 482 | bool pressStart; 483 | bool seqRunning = false; 484 | int seqStep; 485 | int prevSeqStep; 486 | int seqPage; 487 | bool seqStepClearFlag; 488 | unsigned long seqStepClearTimeStamp; 489 | bool stepActive[8]; 490 | int seqLength = 7; 491 | int seqLengthArray[4] = {7,15,23,31}; 492 | 493 | unsigned long prevMetroTime; 494 | 495 | //Menu 496 | bool menuActive; 497 | bool seqEditActive; 498 | int menuPage; 499 | unsigned long clearTimeStamp; 500 | 501 | 502 | 503 | 504 | //peaks 505 | AudioAnalyzePeak *peaks[8] = { 506 | &vPeak1,&vPeak2,&vPeak3,&vPeak4, 507 | &vPeak5,&vPeak6,&vPeak7,&vPeak8, 508 | }; 509 | //envelopes 510 | AudioEffectEnvelope *envs[8] = { 511 | &envelope1,&envelope2,&envelope3,&envelope4, 512 | &envelope5,&envelope6,&envelope7,&envelope8, 513 | }; 514 | //modulators 515 | AudioSynthWaveformModulated *mods[8] = { 516 | &modu1,&modu2,&modu3,&modu4, 517 | &modu5,&modu6,&modu7,&modu8, 518 | }; 519 | //carriers 520 | AudioSynthWaveformSineModulated *cars[8] = { 521 | &carA1,&carA2,&carA3,&carA4, 522 | &carA5,&carA6,&carA7,&carA8, 523 | }; 524 | //sawsA 525 | AudioSynthWaveformModulated *sawsA[8] = { 526 | &sawA1,&sawA2,&sawA3,&sawA4, 527 | &sawA5,&sawA6,&sawA7,&sawA8, 528 | }; 529 | //sawsB 530 | AudioSynthWaveformModulated *sawsB[8] = { 531 | &sawB1,&sawB2,&sawB3,&sawB4, 532 | &sawB5,&sawB6,&sawB7,&sawB8, 533 | }; 534 | //Triangles 535 | AudioSynthWaveform *trinagles[8] = { 536 | &tri1,&tri2,&tri3,&tri4, 537 | &tri5,&tri6,&tri7,&tri8, 538 | }; 539 | //Filters 540 | AudioFilterStateVariable *filters[8] = { 541 | &filter1,&filter2,&filter3,&filter4, 542 | &filter5,&filter6,&filter7,&filter8, 543 | }; 544 | //VoiceMixers 545 | AudioMixer4 *voiceMixers[8] = { 546 | &voiceMixer1,&voiceMixer2,&voiceMixer3,&voiceMixer4, 547 | &voiceMixer5,&voiceMixer6,&voiceMixer7,&voiceMixer8, 548 | }; 549 | //lfoPitch 550 | AudioSynthWaveform *pitchLfos[8] = { 551 | &lfoPitch1,&lfoPitch2,&lfoPitch3,&lfoPitch4, 552 | &lfoPitch5,&lfoPitch6,&lfoPitch7,&lfoPitch8, 553 | }; 554 | //envFilter 555 | AudioEffectEnvelope *filEnv[8] = { 556 | &filEnv1,&filEnv2,&filEnv3,&filEnv4, 557 | &filEnv5,&filEnv6,&filEnv7,&filEnv8, 558 | }; 559 | 560 | AudioSynthWaveformDc *dcs[8] = { 561 | &dc1,&dc2,&dc3,&dc4, 562 | &dc5,&dc6,&dc7,&dc8, 563 | }; 564 | 565 | 566 | String paramNames[24]{ 567 | "Main Vol: ","Attack: ","Decay: ","Octave: ","FM Index: ", 568 | "Voice Mix: ", "Filter: ","Lfo One Speed: ","Lfo One Amt: ", 569 | "Filter Env Attack: ", "Filter Env Decay: ", 570 | "Verb: ", "Lfo Audio Rate: ","Filter Env Loop: ","Y to Mix: ", 571 | "Y to Filter: ", "Y to Lfo One Speed: ", "Y to Lfo One Amt: ", 572 | "Y to Lfo 2 Attack: ", "Y to Lfo 2 Decay: ", "Unison Detune: ", 573 | "Unison Glide Amt: ", "Unison On: ", "Glide On: " 574 | }; 575 | 576 | 577 | void setup() { 578 | Serial.begin(9600); 579 | 580 | AudioMemory(48); 581 | 582 | usbMIDI.setHandleRealTimeSystem(RealTimeSystem); 583 | usbMIDI.setHandleNoteOff(OnNoteOff); 584 | usbMIDI.setHandleNoteOn(OnNoteOn); 585 | usbMIDI.setHandleControlChange(OnControlChange); 586 | 587 | for(int i=0; i<8; i++){ 588 | //Envelopes 589 | envs[i]->delay(0); 590 | envs[i]->decay(0); 591 | envs[i]->hold(0); 592 | envs[i]->sustain(1); 593 | envs[i]->releaseNoteOn(2); 594 | //Filter Envs 595 | filEnv[i]->delay(0); 596 | filEnv[i]->attack(0); 597 | filEnv[i]->decay(1000); 598 | filEnv[i]->hold(0); 599 | filEnv[i]->sustain(0); 600 | filEnv[i]->releaseNoteOn(2); 601 | 602 | 603 | //modulators 604 | mods[i]->begin(1,0,WAVEFORM_SINE); 605 | //Carriers 606 | cars[i]->amplitude(1); 607 | cars[i]->mod_index(65535.0); 608 | //Saws 609 | sawsA[i]->begin(.25,0,WAVEFORM_SQUARE); 610 | sawsA[i]->frequencyModulation(12); 611 | sawsB[i]->begin(.25,0,WAVEFORM_SAWTOOTH); 612 | trinagles[i]->begin(.25,0,WAVEFORM_TRIANGLE); 613 | //Filters 614 | filters[i]->resonance(1.5); 615 | filters[i]->octaveControl(7); 616 | //lfos 617 | pitchLfos[i]->begin(0,0,WAVEFORM_SINE); 618 | dcs[i]->amplitude(1); 619 | } 620 | 621 | //Mixers 622 | preMix1.gain(0,.25); 623 | preMix1.gain(1,.25); 624 | preMix1.gain(2,.25); 625 | preMix1.gain(3,.25); 626 | preMix2.gain(0,.25); 627 | preMix2.gain(1,.25); 628 | preMix2.gain(2,.25); 629 | preMix2.gain(3,.25); 630 | 631 | finalMixer.gain(0,.5); 632 | finalMixer.gain(1,.5); 633 | finalMixer.gain(2,.5); 634 | //Verb 635 | freeverb1.roomsize(1); 636 | freeverb1.damping(.5); 637 | 638 | pinMode(25, INPUT_PULLUP); 639 | pinMode(13, INPUT_PULLUP); 640 | pinMode(14, INPUT_PULLUP); 641 | pinMode(ClkInPin, INPUT); 642 | 643 | //ENCODER KNOB 644 | pinMode(encoderPin1, INPUT); 645 | pinMode(encoderPin2, INPUT); 646 | digitalWrite(encoderPin1, HIGH); 647 | digitalWrite(encoderPin2, HIGH); 648 | attachInterrupt(encoderPin1, updateEncoder, CHANGE); 649 | attachInterrupt(encoderPin2, updateEncoder, CHANGE); 650 | 651 | LEDS.addLeds(leds,NUM_LEDS); 652 | LEDS.setBrightness(40); 653 | for(int i=0; i 30){ 682 | if(slaveFlag){ 683 | doubleInterval = millis() - pulseInStamp; 684 | } 685 | pulseInStamp = millis(); 686 | slaveFlag = true; 687 | seqRunning = true; 688 | doubleStep = true; 689 | seqStep++; 690 | } 691 | last_interrupt_time = interrupt_time; 692 | } 693 | 694 | void loop() { 695 | //Serial.println(AudioMemoryUsageMax()); 696 | 697 | //MIDI In 698 | usbMIDI.read(); 699 | 700 | //loopEnv 701 | if(loopEnv){ 702 | for(int i=0; i<8; i++){ 703 | if(filEnv[i]->isSustain()){ 704 | filEnv[i]->noteOn(); 705 | } 706 | } 707 | } 708 | 709 | 710 | 711 | //Blink 712 | blinkBrightness = 128+127*cos(2*PI/metroInterval*millis()); 713 | //BlnkConst 714 | blinkControl = 128+127*cos(2*PI/500*millis()); 715 | 716 | //Encoder Knob 717 | if (abs(scaledEncVal - prevScaledEncVal) > 0){ 718 | if(menuActive && !seqEditActive){ 719 | menuPage = scaledEncVal; 720 | savePresetCheck = false; 721 | lightsOut(); 722 | }else if (menuActive && seqEditActive){ 723 | seqStep = scaledEncVal; 724 | } 725 | prevScaledEncVal = scaledEncVal; 726 | } 727 | 728 | //Clock 729 | if((seqRunning && !slaveFlag)){ 730 | if(millis() - prevMetroTime > metroInterval){ 731 | seqStep++; 732 | prevMetroTime = millis(); 733 | } 734 | } 735 | 736 | //Slave Double Time 737 | if(millis() >= (pulseInStamp + doubleInterval/2) && slaveFlag && doubleStep){ 738 | seqStep++; 739 | doubleStep = false; 740 | } 741 | 742 | 743 | //Sequencer 744 | if(seqEditActive || seqRunning){ 745 | if(!presetLoading){ 746 | if(abs(seqStep - prevSeqStep) > 0){ 747 | if(slaveFlag && seqStep % 2 == 0){ 748 | digitalWrite(ClkOutPin, HIGH); 749 | }else if(!slaveFlag){ 750 | digitalWrite(ClkOutPin, HIGH); 751 | } 752 | if (seqRunning){ 753 | if (seqStep > seqLength){ 754 | seqStep = 0; 755 | } 756 | }else{ 757 | if (seqStep > 31){ 758 | seqStep = 0; 759 | } 760 | } 761 | 762 | seqPage = (seqStep/8)*8; 763 | 764 | if(!menuActive || (menuActive && seqEditActive)){ 765 | lightsOut(); 766 | leds[seqStep%8].setRGB(100,100,100); 767 | } 768 | 769 | //Notes Off 770 | seqNotesOff(); 771 | 772 | //Notes On 773 | for(int s=0; s<8; s++){ 774 | if(seqNotes[seqStep][s]){ 775 | int noteRef = seqNotes[seqStep][s]-1; 776 | frequency[s] = noteFrequencies[scale][noteRef]; 777 | if(unisonMode){ 778 | newFreq = frequency[s]; 779 | for (int j = 0; j < 8; ++j){ 780 | envs[j]->noteOn(); 781 | filEnv[j]->noteOn(); 782 | } 783 | }else{ 784 | envs[s]->noteOn(); 785 | filEnv[s]->noteOn(); 786 | stepActive[s] = true; 787 | } 788 | } 789 | } 790 | //Params 791 | if(!seqEditActive){ 792 | for(int i=0; i<14; i++){ 793 | if(seqParams[seqStep][i]){ 794 | if(i>11){ 795 | setSynthParams(i, seqParams[seqStep][i]-1); 796 | }else{ 797 | setSynthParams(i, seqParams[seqStep][i]); 798 | } 799 | } 800 | } 801 | } 802 | 803 | prevSeqStep = seqStep; 804 | }else{ 805 | digitalWrite(ClkOutPin, LOW); 806 | } 807 | } 808 | //Seq lights 809 | if(!menuActive || (menuActive && seqEditActive)){ 810 | for(int s=0; s<8; s++){ 811 | for(int i=0; i<8; i++){ 812 | if(seqNotes[s+seqPage][i]){ 813 | if(seqStep%8 == s){ 814 | leds[s].setRGB(255,255,0); 815 | }else{ 816 | leds[s].setRGB(colorArray[(seqPage/8)+4][0],colorArray[(seqPage/8)+4][1],colorArray[(seqPage/8)+4][2]); 817 | } 818 | } 819 | } 820 | } 821 | } 822 | } 823 | 824 | //Encoder Btn 825 | if(swBouncers[0].update() && digitalRead(swPins[0]) == 0){ 826 | if((millis() - clearTimeStamp) < 300){ 827 | clearEverything(); 828 | }else{ 829 | clearTimeStamp = millis(); 830 | if(!seqEditActive){ 831 | menuActive = !menuActive; 832 | savePresetCheck = false; 833 | if(menuActive) lightsOut();//menuDisplay(); 834 | }else{ 835 | knobThresh = 8; 836 | seqEditActive = false; 837 | lightsOut(); 838 | //menuDisplay(); 839 | seqNotesOff(); 840 | } 841 | } 842 | } 843 | //Switches 844 | for(int i=1; i<3; i++){ 845 | if (swBouncers[i].update() || firstRun){ 846 | paramVals[i+11] = digitalRead(swPins[i]); 847 | setSynthParams(i+11,paramVals[i+11]); 848 | //Seq Param Automation 849 | if(seqEditActive){ 850 | seqParams[seqStep][i+11] = paramVals[i+11]+1; 851 | } 852 | } 853 | } 854 | 855 | //Knobs 856 | for (int i = 0; i < 12; ++i){ 857 | analogValues[i] = analogRead(analogPins[i]); 858 | if ((abs(analogValues[i] - analogValuesLag[i]) > knobThresh) || firstRun){ 859 | if(knobLocks[i] && (abs((analogValues[i]/4) - paramVals[i]) < 20)){ 860 | knobLocks[i] = false; 861 | } 862 | if(!knobLocks[i]){ 863 | if(menuActive && menuPage == 4 && i==3 && unisonMode){ 864 | paramVals[20] = analogValues[i] / 4; 865 | setSynthParams(20, paramVals[20]); 866 | }else if (menuActive && menuPage == 4 && i==4 && unisonMode){ 867 | paramVals[21] = analogValues[i] / 4; 868 | setSynthParams(21, paramVals[21]); 869 | }else{ 870 | paramVals[i] = analogValues[i] / 4; 871 | setSynthParams(i, paramVals[i]); 872 | } 873 | if(seqEditActive){ 874 | seqParams[seqStep][i] = paramVals[i]; 875 | } 876 | } 877 | //save Seq Automation 878 | analogValuesLag[i] = analogValues[i]; 879 | } 880 | } 881 | 882 | AudioNoInterrupts(); 883 | for(int i=0; i<8; i++){ 884 | mods[i]->frequency(frequency[i] * fmRatioArray[fmIndex] * octArray[octIndex]); 885 | cars[i]->frequency((frequency[i] * octArray[octIndex])); 886 | sawsA[i]->frequency(frequency[i] * octArray[octIndex]); 887 | sawsB[i]->frequency(frequency[i] * octArray[octIndex]); 888 | trinagles[i]->frequency((frequency[i] * octArray[octIndex])/2); 889 | if(!yToMix){ 890 | voiceMixers[i]->gain(0,voiceMixerVal[i]); 891 | voiceMixers[i]->gain(2,1 - voiceMixerVal[i]); 892 | } 893 | if(!yToFilter){ 894 | filters[i]->frequency(filterMulti); 895 | mods[i]->amplitude(fmMulti); 896 | } 897 | if(!ytoLfoOneAmt){ 898 | if(superLfo){ 899 | pitchLfos[i]->amplitude(lfoOneAmt); 900 | }else{ 901 | pitchLfos[i]->amplitude(lfoOneAmt/100); 902 | } 903 | } 904 | if(!ytofilEnvDecay){ 905 | filEnv[i]->decay(filEnvDecay); 906 | } 907 | if(!yTolfoOneSpeed){ 908 | if(superLfo){ 909 | pitchLfos[i]->frequency(frequency[i]*fmRatioArray[superIndex]* octArray[octIndex]); 910 | }else{ 911 | pitchLfos[i]->frequency(lfoOneFreq); 912 | } 913 | } 914 | if(!yTofilEnvAttack){ 915 | filEnv[i]->attack(filEnvAttack); 916 | } 917 | } 918 | verbMixer.gain(0,1 - verbMix); 919 | verbMixer.gain(1,verbMix); 920 | AudioInterrupts(); 921 | 922 | 923 | //TOUCH STUFF 924 | for (int i = 0; i < 8; ++i){ 925 | envTrig[i] = touchRead(noteTouchPins[i]); 926 | 927 | if ((envTrig[i] > noTouchVal[i]+100) && noteTouched[i] == false){ 928 | noteTouched[i] = true; 929 | if(menuActive){ 930 | menuActions(i); 931 | }else{ 932 | AudioNoInterrupts(); 933 | if(unisonMode){ 934 | newFreq = noteFrequencies[scale][i]; 935 | for (int j = 0; j < 8; ++j){ 936 | envs[j]->noteOn(); 937 | filEnv[j]->noteOn(); 938 | allOff[j] = false; 939 | } 940 | }else{ 941 | frequency[i] = noteFrequencies[scale][i]; 942 | envs[i]->noteOn(); 943 | filEnv[i]->noteOn(); 944 | } 945 | AudioInterrupts(); 946 | } 947 | }else if ((envTrig[i] < noTouchVal[i]+100) && noteTouched[i] == true){ 948 | noteTouched[i] = false; 949 | if(!menuActive || (menuPage == 3 && seqEditActive)){ 950 | AudioNoInterrupts(); 951 | if(unisonMode){ 952 | for (int j = 0; j < 8; ++j){ 953 | if((envTrig[j] < noTouchVal[j]+100)){ 954 | allOff[j] = true; 955 | } 956 | } 957 | if(allOff[0] && allOff[1] && allOff[2] && allOff[3] && allOff[4] && allOff[5] && allOff[6] && allOff[7]){ 958 | for (int j = 0; j < 8; ++j){ 959 | envs[j]->noteOff(); 960 | //filEnv[j]->noteOff(); 961 | } 962 | } 963 | }else{ 964 | envs[i]->noteOff(); 965 | //filEnv[i]->noteOff(); 966 | } 967 | AudioInterrupts(); 968 | } 969 | } 970 | 971 | if(glide){ 972 | if(oldFreq < newFreq){ 973 | oldFreq = oldFreq * glideSpeed; 974 | }else if(oldFreq > newFreq){ 975 | oldFreq = oldFreq / glideSpeed; 976 | } 977 | }else{ 978 | oldFreq = newFreq; 979 | } 980 | 981 | if(unisonMode){ 982 | for(int k=0; k<8; k++){ 983 | frequency[k] = oldFreq*detuneAmt[k]; 984 | } 985 | } 986 | 987 | //Modulation Source 988 | if(seqNotes[seqStep][i] && seqRunning){ 989 | scaledYpos[i] = mapfloat(seqYpos[seqStep][i], noTouchVal[i], 5000, .1, 2); 990 | }else{ 991 | scaledYpos[i] = mapfloat(envTrig[i], noTouchVal[i], 5000, .1, 2); 992 | } 993 | 994 | if(noteTouched[i] || (seqNotes[seqStep][i] && noteTouched[i] && seqEditActive) || (seqNotes[seqStep][i] && seqRunning)){ 995 | 996 | if(abs(scaledYpos[i] - prevScaledYpos[i]) < .5){ 997 | if(seqEditActive){ 998 | seqYpos[seqStep][i] = envTrig[i]; 999 | } 1000 | //Voice Modulation 1001 | AudioNoInterrupts(); 1002 | if(yToFilter){ 1003 | filters[i]->frequency(pow(filterMulti,scaledYpos[i])); 1004 | mods[i]->amplitude(fmMulti*scaledYpos[i]); 1005 | } 1006 | if(yToMix){ 1007 | voiceMixers[i]->gain(0,scaledYpos[i]/2); 1008 | voiceMixers[i]->gain(2,1 - (scaledYpos[i]/2)); 1009 | } 1010 | if(ytoLfoOneAmt){ 1011 | if(superLfo){ 1012 | pitchLfos[i]->amplitude(lfoOneAmt*scaledYpos[i]); 1013 | }else{ 1014 | pitchLfos[i]->amplitude((lfoOneAmt/100)*scaledYpos[i]); 1015 | } 1016 | } 1017 | if(ytofilEnvDecay){ 1018 | filEnv[i]->decay(filEnvDecay/scaledYpos[i]); 1019 | } 1020 | if(yTolfoOneSpeed){ 1021 | if(superLfo){ 1022 | pitchLfos[i]->frequency(frequency[i]*scaledYpos[i]*fmRatioArray[superIndex]* octArray[octIndex]); 1023 | }else{ 1024 | pitchLfos[i]->frequency(pow(lfoOneFreq,scaledYpos[i])); 1025 | } 1026 | } 1027 | if(yTofilEnvAttack){ 1028 | filEnv[i]->attack(filEnvAttack/scaledYpos[i]); 1029 | } 1030 | AudioInterrupts(); 1031 | } 1032 | prevScaledYpos[i] = scaledYpos[i]; 1033 | } 1034 | } 1035 | 1036 | //blink tap tempo 1037 | if(menuActive){ 1038 | menuDisplay(); 1039 | } 1040 | //Light notes//peaks 1041 | for(int i=0; i<8; i++){ 1042 | if(peaks[i]->available()){ 1043 | voicePeaks[i] = peaks[i]->read(); 1044 | if(!menuActive && !seqRunning){ 1045 | leds[i].setRGB(colorArray[i][0]*voicePeaks[i],colorArray[i][1]*voicePeaks[i],colorArray[i][2]*voicePeaks[i]); 1046 | } 1047 | }else{ 1048 | if(!menuActive && !seqRunning){ 1049 | leds[i].setRGB(0,0,0); 1050 | } 1051 | } 1052 | } 1053 | //Save Preset Check 1054 | if(savePresetCheck && menuActive && menuPage==1){ 1055 | leds[presetNum].setRGB(blinkBrightness, 0, 0); 1056 | } 1057 | //Kill Slave 1058 | if((millis() - pulseInStamp > 2000) && slaveFlag){ 1059 | doubleInterval = 200; 1060 | slaveFlag = false; 1061 | seqRunning = false; 1062 | doubleStep = false; 1063 | resetSeq(); 1064 | seqNotesOff(); 1065 | } 1066 | 1067 | FastLED.show(); 1068 | firstRun = false; 1069 | 1070 | } 1071 | void OnControlChange(byte channel, byte control, byte value){ 1072 | //Serial.println("CC: "+String(control)+" Val: "+String(value)); 1073 | setSynthParams(control-1, value*2); 1074 | } 1075 | 1076 | void OnNoteOn(byte channel, byte note, byte velocity){ 1077 | float freq = 440.0 * powf(2.0, (float)(note - 69) * 0.08333333); 1078 | AudioNoInterrupts(); 1079 | voiceNum = lowestAmp(); 1080 | for(int i=0; i<8; i++){ 1081 | if (voiceUsed[voiceNum]){ 1082 | voiceNum++; 1083 | if (voiceNum > 7){ 1084 | voiceNum = 0; 1085 | } 1086 | } 1087 | } 1088 | voiceUsed[voiceNum] = freq; 1089 | frequency[voiceNum] = freq; 1090 | 1091 | if(unisonMode){ 1092 | newFreq = freq; 1093 | for(int i=0; i<8; i++){ 1094 | envs[i]->noteOn(); 1095 | filEnv[i]->noteOn(); 1096 | } 1097 | }else{ 1098 | envs[voiceNum]->noteOn(); 1099 | filEnv[voiceNum]->noteOn(); 1100 | } 1101 | AudioInterrupts(); 1102 | } 1103 | 1104 | void OnNoteOff(byte channel, byte note, byte velocity){ 1105 | float freq = 440.0 * powf(2.0, (float)(note - 69) * 0.08333333); 1106 | AudioNoInterrupts(); 1107 | for (int i = 0; i < 8; ++i){ 1108 | if(unisonMode){ 1109 | if(newFreq == freq){ 1110 | voiceUsed[i] = 0; 1111 | envs[i]->noteOff(); 1112 | } 1113 | }else{ 1114 | if(frequency[i] == freq){ 1115 | voiceUsed[i] = 0; 1116 | envs[i]->noteOff(); 1117 | } 1118 | } 1119 | } 1120 | AudioInterrupts(); 1121 | } 1122 | 1123 | int lowestAmp(){ 1124 | int index = 0; 1125 | for (int i = 0; i < 8; i++){ 1126 | if (voicePeaks[i] < voicePeaks[index]) { 1127 | index = i; 1128 | } 1129 | } 1130 | return index; 1131 | } 1132 | 1133 | 1134 | void seqNotesOff(){ 1135 | for(int s=0; s<8; s++){ 1136 | if(stepActive[s] || unisonMode){ 1137 | envs[s]->noteOff(); 1138 | //filEnv[s]->noteOff(); 1139 | stepActive[s] = false; 1140 | } 1141 | } 1142 | } 1143 | void resetSeq(){ 1144 | seqStep = seqLength; 1145 | prevSeqStep = seqStep; 1146 | } 1147 | 1148 | void menuDisplay(){ 1149 | //lightsOut(); 1150 | for(int i=0; i<8; i++){ 1151 | if(menuPage == 0){ 1152 | leds[i].setRGB(0,255,0); 1153 | }else if(menuPage == 1){ 1154 | leds[i].setRGB(255,0,0); 1155 | } 1156 | } 1157 | if(menuPage == 2){ 1158 | leds[scale].setRGB(255,255,0); 1159 | } 1160 | 1161 | if(menuPage == 3 && !seqEditActive){ 1162 | if(tapTempoFlag){ 1163 | leds[1].setRGB(255,0,0); 1164 | }else{ 1165 | if(seqRunning){ 1166 | leds[1].setRGB(blinkBrightness,0,blinkBrightness); 1167 | }else{ 1168 | leds[1].setRGB(255,0,255); 1169 | } 1170 | } 1171 | for(int i=0; i<8; i++){ 1172 | for(int i=0; i<8; i++){ 1173 | if(seqRunning){ 1174 | leds[0].setRGB(0,255,0); 1175 | }else{ 1176 | leds[0].setRGB(0,0,255); 1177 | } 1178 | leds[2].setRGB(255,255,255); 1179 | 1180 | if(i > 3){ 1181 | leds[i].setRGB(0,0,255); 1182 | } 1183 | } 1184 | if(seqLength == 7){ 1185 | leds[4].setRGB(255,255,0); 1186 | }else if(seqLength == 15){ 1187 | leds[5].setRGB(255,255,0); 1188 | }else if(seqLength == 23){ 1189 | leds[6].setRGB(255,255,0); 1190 | }else{ 1191 | leds[7].setRGB(255,255,0); 1192 | } 1193 | } 1194 | }else if(menuPage == 3 && seqEditActive){ 1195 | if(lightStepZero){ 1196 | leds[0].setRGB(100,100,100); 1197 | lightStepZero = false; 1198 | } 1199 | } 1200 | if(menuPage == 0 || menuPage == 1){ 1201 | if(presetLoaded){ 1202 | leds[presetNum].setRGB(0,0,255); 1203 | } 1204 | } 1205 | //Special Ypos 1206 | if(menuPage == 4){ 1207 | unisonMode ? leds[0].setRGB(blinkControl,blinkControl,blinkControl) : leds[0].setRGB(255,255,255); 1208 | glide ? leds[1].setRGB(0,blinkControl,blinkControl) : leds[1].setRGB(0,255,255); 1209 | yToMix ? leds[2].setRGB(blinkControl,0,0) : leds[2].setRGB(255,0,0); 1210 | yToFilter ? leds[3].setRGB(0,blinkControl,0) : leds[3].setRGB(0,255,0); 1211 | yTolfoOneSpeed ? leds[4].setRGB(0,0,blinkControl) : leds[4].setRGB(0,0,255); 1212 | ytoLfoOneAmt ? leds[5].setRGB(0,blinkControl,blinkControl) : leds[5].setRGB(0,255,255); 1213 | yTofilEnvAttack ? leds[6].setRGB(blinkControl,0,blinkControl) : leds[6].setRGB(255,0,255); 1214 | ytofilEnvDecay ? leds[7].setRGB(blinkControl,blinkControl,0) : leds[7].setRGB(255,255,0); 1215 | } 1216 | } 1217 | void menuActions(int i){ 1218 | switch (menuPage) { 1219 | case 0: 1220 | loadPreset(i*24); 1221 | presetNum = i; 1222 | lightsOut(); 1223 | break; 1224 | case 1: 1225 | presetNum = i; 1226 | if(savePresetCheck){ 1227 | savePreset(i*24); 1228 | lightsOut(); 1229 | savePresetCheck = false; 1230 | }else{ 1231 | savePresetCheck = true; 1232 | } 1233 | break; 1234 | case 2: 1235 | scale = i; 1236 | lightsOut(); 1237 | break; 1238 | case 3: 1239 | if(seqEditActive){ 1240 | AudioNoInterrupts(); 1241 | if(unisonMode){ 1242 | newFreq = noteFrequencies[scale][i]; 1243 | for(int j=0; j<8; j++){ 1244 | envs[j]->noteOn(); 1245 | filEnv[j]->noteOn(); 1246 | allOff[j] = false; 1247 | } 1248 | }else{ 1249 | frequency[i] = noteFrequencies[scale][i]; 1250 | envs[i]->noteOn(); 1251 | filEnv[i]->noteOn(); 1252 | } 1253 | AudioInterrupts(); 1254 | if(!seqNotes[seqStep][i]){ 1255 | seqNotes[seqStep][i] = i+1; 1256 | leds[seqStep%8].setRGB(0,255,0); 1257 | }else{ 1258 | seqNotes[seqStep][i] = false; 1259 | seqNotesOff(); 1260 | if(!seqNotes[seqStep][i]){ 1261 | leds[seqStep%8].setRGB(100,100,100); 1262 | } 1263 | } 1264 | }else{ 1265 | if(i == 0){ 1266 | seqRunning = !seqRunning; 1267 | if(!seqRunning){ 1268 | for(int n=0; n<8; n++){ 1269 | AudioNoInterrupts(); 1270 | envs[n]->noteOff(); 1271 | AudioInterrupts(); 1272 | } 1273 | }else{ 1274 | resetSeq(); 1275 | pressStart = true; 1276 | } 1277 | }else if(i == 1){ 1278 | tapTempoFlag = true; 1279 | tapTempTimeStamp[tapTempoAmount] = millis(); 1280 | tapTempoAmount++; 1281 | if(tapTempoAmount > 3){ 1282 | float tapAverageOne; 1283 | tapAverageOne = tapTempTimeStamp[1] - tapTempTimeStamp[0]; 1284 | float tapAverageTwo; 1285 | tapAverageTwo = tapTempTimeStamp[2] - tapTempTimeStamp[1]; 1286 | float tapAverageThree; 1287 | tapAverageThree = tapTempTimeStamp[3] - tapTempTimeStamp[2]; 1288 | float totalTapAverage; 1289 | totalTapAverage = ((tapAverageOne+tapAverageTwo+tapAverageThree)/3); 1290 | metroInterval = totalTapAverage; 1291 | tapTempoAmount = 0; 1292 | tapTempoFlag = false; 1293 | } 1294 | }else if(i == 2){ 1295 | seqEditActive = true; 1296 | seqRunning = false; 1297 | encoderValue = 0; 1298 | knobThresh = 20; 1299 | lightStepZero = true; 1300 | }else if(i > 3){ 1301 | seqLength = seqLengthArray[i-4]; 1302 | } 1303 | lightsOut(); 1304 | } 1305 | break; 1306 | case 4: 1307 | if(i==0) unisonMode ? setSynthParams(22,0) : setSynthParams(22,1); 1308 | if(i==1) glide ? setSynthParams(23,0) : setSynthParams(23,1); 1309 | if(i==2) yToMix ? setSynthParams(14,0) : setSynthParams(14,1); 1310 | if(i==3) yToFilter ? setSynthParams(15,0) : setSynthParams(15,1); 1311 | if(i==4) yTolfoOneSpeed ? setSynthParams(16,0) : setSynthParams(16,1); 1312 | if(i==5) ytoLfoOneAmt ? setSynthParams(17,0) : setSynthParams(17,1); 1313 | if(i==6) yTofilEnvAttack ? setSynthParams(18,0) : setSynthParams(18,1); 1314 | if(i==7) ytofilEnvDecay ? setSynthParams(19,0) : setSynthParams(19,1); 1315 | break; 1316 | } 1317 | } 1318 | void lightsOut(){ 1319 | for(int i=0; i<8; i++){ 1320 | leds[i].setRGB(0,0,0); 1321 | } 1322 | } 1323 | void loadPreset(int presetNumber){ 1324 | AudioNoInterrupts(); 1325 | presetLoading = true; 1326 | for(int i=0; i<24; i++){ 1327 | if(i<8){ 1328 | filEnv[i]->noteOff(); 1329 | envs[i]->noteOff(); 1330 | } 1331 | paramVals[i] = EEPROM.read(i+presetNumber); 1332 | setSynthParams(i, EEPROM.read(i+presetNumber)); 1333 | Serial.println(paramNames[i] + String(paramVals[i])); 1334 | 1335 | if(i<12){ 1336 | knobLocks[i] = true; 1337 | } 1338 | } 1339 | presetLoaded = true; 1340 | presetLoading = false; 1341 | menuActive = false; 1342 | AudioInterrupts(); 1343 | } 1344 | void savePreset(int presetNumber){ 1345 | AudioNoInterrupts(); 1346 | for(int i=0; i<24; i++){ 1347 | EEPROM.write(i+presetNumber, paramVals[i]); 1348 | Serial.println(paramNames[i] + String(paramVals[i])); 1349 | } 1350 | presetLoaded = true; 1351 | menuActive = false; 1352 | AudioInterrupts(); 1353 | } 1354 | 1355 | 1356 | 1357 | void setSynthParams(int paramNum, float paramVal){ 1358 | // Serial.print(paramNum); 1359 | // Serial.print(":: "); 1360 | // Serial.println(paramVal); 1361 | 1362 | AudioNoInterrupts(); 1363 | if(paramNum < 12 || paramNum == 20 || paramNum == 21){ 1364 | paramVal = paramVal * 4; 1365 | } 1366 | switch (paramNum) { 1367 | case 0: 1368 | //Main Vol 1369 | finalMixer.gain(0,paramVal/1023); 1370 | finalMixer.gain(1,paramVal/1023); 1371 | break; 1372 | case 1: 1373 | //Attack 1374 | for(int i=0; i<8; i++){ 1375 | envs[i]->attack((paramVal * 4) + 5); 1376 | } 1377 | break; 1378 | case 2: 1379 | //Decay 1380 | for(int i=0; i<8; i++){ 1381 | envs[i]->release((paramVal * 4) + 5); 1382 | } 1383 | break; 1384 | case 3: 1385 | //Octave 1386 | octIndex = paramVal / 204.6; 1387 | octIndex = constrain(octIndex, 0, 4); 1388 | break; 1389 | case 4: 1390 | //FM Index 1391 | fmIndex = paramVal / 113.6; 1392 | fmIndex = constrain(fmIndex, 0, 8); 1393 | break; 1394 | case 5: 1395 | //VoiceMixer 1396 | for(int i=0; i<8; i++){ 1397 | voiceMixerVal[i] = paramVal / 1023; 1398 | } 1399 | break; 1400 | case 6: 1401 | //Filter Res and FMAmp 1402 | filterMulti = (paramVal*2)+10; 1403 | fmMulti = (paramVal / 10230)+.01; 1404 | break; 1405 | case 7: 1406 | //LFO One Freq 1407 | if(superLfo){ 1408 | superIndex = paramVal / 113.6;; 1409 | superIndex = constrain(superIndex, 0, 8); 1410 | }else{ 1411 | lfoOneFreq = paramVal / 128; 1412 | } 1413 | break; 1414 | case 8: 1415 | //LFO One Amt 1416 | lfoOneAmt = paramVal/1023; 1417 | break; 1418 | case 9: 1419 | //filter env Attack 1420 | filEnvAttack = paramVal*4; 1421 | break; 1422 | case 10: 1423 | //filter env Decay 1424 | filEnvDecay = paramVal*4; 1425 | break; 1426 | case 11: 1427 | //Verb Mix 1428 | verbMix = paramVal/3069; 1429 | break; 1430 | case 12: 1431 | //LFO Audio Rate 1432 | paramVal ? superLfo = true : superLfo = false; 1433 | break; 1434 | case 13: 1435 | //filter env loop 1436 | paramVal ? loopEnv = true : loopEnv = false; 1437 | break; 1438 | case 14: 1439 | //Y-to-Mix 1440 | paramVal ? yToMix = true : yToMix = false; 1441 | paramVals[14] = yToMix; 1442 | break; 1443 | case 15: 1444 | //Y-to-filter 1445 | paramVal ? yToFilter = true : yToFilter = false; 1446 | paramVals[15] = yToFilter; 1447 | break; 1448 | case 16: 1449 | //Y-to-LFO One Speed 1450 | paramVal ? yTolfoOneSpeed = true : yTolfoOneSpeed = false; 1451 | paramVals[16] = yTolfoOneSpeed; 1452 | break; 1453 | case 17: 1454 | //Y-to-LFO One Amt 1455 | paramVal ? ytoLfoOneAmt = true : ytoLfoOneAmt = false; 1456 | paramVals[17] = ytoLfoOneAmt; 1457 | break; 1458 | case 18: 1459 | //Y-to-LFO Two Attack 1460 | paramVal ? yTofilEnvAttack = true : yTofilEnvAttack = false; 1461 | paramVals[18] = yTofilEnvAttack; 1462 | break; 1463 | case 19: 1464 | //Y-to-LFO Two Decay 1465 | paramVal ? ytofilEnvDecay = true : ytofilEnvDecay = false; 1466 | paramVals[19] = ytofilEnvDecay; 1467 | break; 1468 | case 20: 1469 | //Unison Detune 1470 | for(int i=0; i<8; i++){ 1471 | detuneAmt[i] = 1+(paramVal/(16368*(i+1))); 1472 | } 1473 | break; 1474 | case 21: 1475 | //Unison Glide Speed 1476 | glideSpeed = mapfloat(paramVal, 0, 1023, 1.0001, 1.01); 1477 | break; 1478 | case 22: 1479 | //Unision On 1480 | paramVal ? unisonMode = true : unisonMode = false; 1481 | paramVals[22] = unisonMode; 1482 | break; 1483 | case 23: 1484 | //Glide On 1485 | paramVal ? glide = true : glide = false; 1486 | paramVals[23] = glide; 1487 | break; 1488 | } 1489 | 1490 | AudioInterrupts(); 1491 | } 1492 | void clearEverything(){ 1493 | firstRun = true; 1494 | presetLoaded = false; 1495 | clearTimeStamp = millis(); 1496 | seqRunning = false; 1497 | //clear notes and params 1498 | for(int s=0; s<32; s++){ 1499 | if(s<12){knobLocks[s] = false;} 1500 | if(s<8){envs[s]->noteOff();} 1501 | for(int a=0; a<14; a++){ 1502 | seqParams[s][a] = false; 1503 | } 1504 | for(int n=0; n<8; n++){ 1505 | seqNotes[s][n] = false; 1506 | seqYpos[s][n] = false; 1507 | } 1508 | } 1509 | seqNotesOff(); 1510 | slaveFlag = false; 1511 | savePresetCheck = false; 1512 | seqEditActive = false; 1513 | knobThresh = 8; 1514 | yToMix = false; 1515 | yToFilter = false; 1516 | yTofilEnvAttack = false; 1517 | yTolfoOneSpeed = false; 1518 | ytoLfoOneAmt = false; 1519 | ytofilEnvDecay = false; 1520 | unisonMode = false; 1521 | glide = false; 1522 | for(int i=0; i<8; i++){ 1523 | leds[i].setRGB(255,0,0); 1524 | FastLED.show(); 1525 | delay(100); 1526 | leds[i].setRGB(0,0,0); 1527 | FastLED.show(); 1528 | } 1529 | menuActive = false; 1530 | lightsOut(); 1531 | } 1532 | void updateEncoder(){ 1533 | int MSB = digitalRead(encoderPin1); //MSB = most significant bit 1534 | int LSB = digitalRead(encoderPin2); //LSB = least significant bit 1535 | 1536 | encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number 1537 | int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value 1538 | 1539 | if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; 1540 | if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; 1541 | 1542 | 1543 | if (encoderValue < 0){ 1544 | encoderValue = 0; 1545 | } 1546 | if(menuActive && !seqEditActive){ 1547 | if(encoderValue > 16) encoderValue = 16; 1548 | }else if(menuActive && seqEditActive){ 1549 | if (encoderValue > 124) encoderValue = 124; 1550 | } 1551 | 1552 | 1553 | scaledEncVal = encoderValue/4; 1554 | 1555 | lastEncoded = encoded; //store this value for next time 1556 | } 1557 | 1558 | float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) 1559 | { 1560 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 1561 | } 1562 | 1563 | 1564 | int average (float * array, int len){ 1565 | long sum = 0L ; 1566 | for (int i = 0 ; i < len ; i++) 1567 | sum += array [i]; 1568 | 1569 | return ((float) sum) / len; 1570 | } 1571 | 1572 | void RealTimeSystem(byte realtimebyte) { 1573 | if(realtimebyte == START || realtimebyte == CONTINUE) { 1574 | counter = 0; 1575 | slaveFlag = false; 1576 | seqRunning = false; 1577 | resetSeq(); 1578 | } 1579 | 1580 | if(realtimebyte == 248) { 1581 | counter++; 1582 | if(counter == 6) { 1583 | counter = 0; 1584 | } 1585 | if(counter == 1){ 1586 | pulseInStamp = millis(); 1587 | slaveFlag = true; 1588 | seqRunning = true; 1589 | seqStep++; 1590 | } 1591 | } 1592 | if(realtimebyte == STOP) { 1593 | seqNotesOff(); 1594 | slaveFlag = false; 1595 | seqRunning = false; 1596 | resetSeq(); 1597 | } 1598 | } 1599 | 1600 | void printTouchInfoInfo(int touchPlate){ 1601 | Serial.print("Touch Change: "); 1602 | Serial.print(touchPlate); 1603 | Serial.print(" : "); 1604 | Serial.print(noTouchVal[touchPlate]); 1605 | Serial.print(" : "); 1606 | Serial.println(currentYPos[touchPlate]); 1607 | } 1608 | 1609 | 1610 | --------------------------------------------------------------------------------