diff --git a/Trellis_M4_Synth_Design/Design_Tool_Synth_TrellisM4/Design_Tool_Synth_TrellisM4.ino b/Trellis_M4_Synth_Design/Design_Tool_Synth_TrellisM4/Design_Tool_Synth_TrellisM4.ino new file mode 100644 index 00000000..0f8ae9ec --- /dev/null +++ b/Trellis_M4_Synth_Design/Design_Tool_Synth_TrellisM4/Design_Tool_Synth_TrellisM4.ino @@ -0,0 +1,190 @@ +/* Audio library demonstration - pocket synth with C major scale and 4 wave types */ +//each row is a different waveform, envelope, and effect set in major scale +// row 0 sine, soft attack, long release ADSR +// row 1 square, hard attack, moderate release, flanger effect +// row 2 sawtooth, hard attack, soft release, chorus effect +// row 3 triangle, medium attack, long release ADSR, multi tap delay + +#include +#include + +Adafruit_NeoTrellisM4 trellis = Adafruit_NeoTrellisM4(); +// Paste your Audio System Design Tool code below this line: +// GUItool: begin automatically generated code +AudioSynthWaveform wave0; //xy=453.84613037109375,254.61540985107422 +AudioSynthWaveform wave1; //xy=453.84613037109375,294.6154098510742 +AudioSynthWaveform wave2; //xy=453.84613037109375,354.6154098510742 +AudioSynthWaveform wave3; //xy=453.84613037109375,404.6154098510742 +AudioEffectEnvelope env0; //xy=602.8461303710938,254.61540985107422 +AudioEffectEnvelope env1; //xy=602.8461303710938,294.6154098510742 +AudioEffectEnvelope env2; //xy=602.8461303710938,354.6154098510742 +AudioEffectEnvelope env3; //xy=602.8461303710938,404.6154098510742 +AudioEffectChorus chorus1; //xy=734.6796264648438,333.14093017578125 +AudioEffectFlange flange1; //xy=737.7564392089844,284.6794891357422 +AudioEffectDelay delay1; //xy=880.7692260742188,582.3077392578125 +AudioMixer4 mixer1; //xy=882.3076171875,284.6154327392578 +AudioMixer4 mixerLeft; //xy=1041.9999389648438,293.84617614746094 +AudioMixer4 mixerRight; //xy=1045.0768432617188,394.6153869628906 +AudioOutputAnalogStereo audioOut; //xy=1212.8461303710938,354.6154098510742 +AudioConnection patchCord1(wave0, env0); +AudioConnection patchCord2(wave1, env1); +AudioConnection patchCord3(wave2, env2); +AudioConnection patchCord4(wave3, env3); +AudioConnection patchCord5(env0, 0, mixer1, 0); +AudioConnection patchCord6(env1, flange1); +AudioConnection patchCord7(env2, chorus1); +AudioConnection patchCord8(env3, delay1); +AudioConnection patchCord9(env3, 0, mixer1, 3); +AudioConnection patchCord10(chorus1, 0, mixer1, 2); +AudioConnection patchCord11(flange1, 0, mixer1, 1); +AudioConnection patchCord12(delay1, 0, mixerLeft, 1); +AudioConnection patchCord13(delay1, 1, mixerLeft, 2); +AudioConnection patchCord14(delay1, 2, mixerRight, 1); +AudioConnection patchCord15(delay1, 3, mixerRight, 2); +AudioConnection patchCord16(mixer1, 0, mixerLeft, 0); +AudioConnection patchCord17(mixer1, 0, mixerRight, 0); +AudioConnection patchCord18(mixerLeft, 0, audioOut, 0); +AudioConnection patchCord19(mixerRight, 0, audioOut, 1); +// GUItool: end automatically generated code + +AudioSynthWaveform *waves[4] = { +&wave0, &wave1, &wave2, &wave3, +}; +short wave_type[4] = { + WAVEFORM_SINE, + WAVEFORM_SQUARE, + WAVEFORM_SAWTOOTH, + WAVEFORM_TRIANGLE, +}; +float cmaj_low[8] = { 130.81, 146.83, 164.81, 174.61, 196.00, 220.00, 246.94, 261.63 }; +float cmaj_high[8] = { 261.6, 293.7, 329.6, 349.2, 392.0, 440.0, 493.9, 523.3 }; +AudioEffectEnvelope *envs[4] = { + &env0, &env1, &env2, &env3, +}; +int n_chorus = 5; +#define CHORUS_DELAY_LENGTH (400*AUDIO_BLOCK_SAMPLES) +short chorusDelayline[CHORUS_DELAY_LENGTH]; + +#define FLANGER_DELAY_LENGTH (6*AUDIO_BLOCK_SAMPLES) +short flangerDelayline[FLANGER_DELAY_LENGTH]; + +void setup(){ + Serial.begin(115200); + //while (!Serial); + + trellis.begin(); + trellis.setBrightness(255); + + AudioMemory(120); + + //Initialize the waveform nodes + wave0.begin(0.85, 50, WAVEFORM_SINE); + wave1.begin(0.4, 50, WAVEFORM_SQUARE); + wave2.begin(0.6, 50, WAVEFORM_SAWTOOTH); + wave3.begin(0.4, 50, WAVEFORM_TRIANGLE); + + // reduce the gain on some channels, so half of the channels + // are "positioned" to the left, half to the right, but all + // are heard at least partially on both ears + mixerLeft.gain(0, 0.3); + mixerLeft.gain(1, 0.1); + mixerLeft.gain(2, 0.5); + + mixerRight.gain(0, 0.3); + mixerRight.gain(1, 0.5); + mixerRight.gain(2, 0.1); + + + // set envelope parameters, for pleasing sound :-) + env0.attack(300); + env0.hold(2); + env0.decay(30); + env0.sustain(0.6); + env0.release(1200); + + env1.attack(10); + env1.hold(2); + env1.decay(30); + env1.sustain(0.6); + env1.release(400); + + env2.attack(10); + env2.hold(20); + env2.decay(30); + env2.sustain(0.6); + env2.release(1000); + + env3.attack(10); + env3.hold(2); + env3.decay(30); + env3.sustain(0.6); + env3.release(600); + + // set delay parameters + delay1.delay(0, 110); + delay1.delay(1, 660); + delay1.delay(2, 220); + delay1.delay(3, 1220); + + // set effects parameters + chorus1.begin(chorusDelayline, CHORUS_DELAY_LENGTH, n_chorus); + flange1.begin(flangerDelayline, FLANGER_DELAY_LENGTH, FLANGER_DELAY_LENGTH/4, FLANGER_DELAY_LENGTH/4, .5); + + + Serial.println("setup done"); + + // Initialize processor and memory measurements + AudioProcessorUsageMaxReset(); + AudioMemoryUsageMaxReset(); +} + +void noteOn(int num){ + int voice = num/8; + float *scale; + if(voice == 0 || voice == 1) scale = cmaj_low; + else scale = cmaj_high; + AudioNoInterrupts(); + waves[voice]->frequency(scale[num%8]); + envs[voice]->noteOn(); + AudioInterrupts(); +} + +void noteOff(int num){ + int voice = num/8; + envs[voice]->noteOff(); +} + +void loop() { + trellis.tick(); + + while(trellis.available()) + { + keypadEvent e = trellis.read(); + int keyindex = e.bit.KEY; + if(e.bit.EVENT == KEY_JUST_PRESSED){ + trellis.setPixelColor(keyindex, Wheel(keyindex * 255 / 32)); // rainbow! + noteOn(keyindex); + } + else if(e.bit.EVENT == KEY_JUST_RELEASED){ + noteOff(keyindex); + trellis.setPixelColor(keyindex, 0); + } + } + delay(10); +} + + +// Input a value 0 to 255 to get a color value. +// The colours are a transition r - g - b - back to r. +uint32_t Wheel(byte WheelPos) { + WheelPos = 255 - WheelPos; + if(WheelPos < 85) { + return Adafruit_NeoPixel::Color(255 - WheelPos * 3, 0, WheelPos * 3); + } + if(WheelPos < 170) { + WheelPos -= 85; + return Adafruit_NeoPixel::Color(0, WheelPos * 3, 255 - WheelPos * 3); + } + WheelPos -= 170; + return Adafruit_NeoPixel::Color(WheelPos * 3, 255 - WheelPos * 3, 0); +} diff --git a/Trellis_M4_Synth_Design/ToneSweep_TrellisM4/ToneSweep_TrellisM4.ino b/Trellis_M4_Synth_Design/ToneSweep_TrellisM4/ToneSweep_TrellisM4.ino new file mode 100644 index 00000000..c913f8bc --- /dev/null +++ b/Trellis_M4_Synth_Design/ToneSweep_TrellisM4/ToneSweep_TrellisM4.ino @@ -0,0 +1,52 @@ +/* + Audio Library on Trellis M4 + Demo of the audio sweep function. + The user specifies the amplitude, + start and end frequencies (which can sweep up or down) + and the length of time of the sweep. + */ + +#include +// Paste your Audio System Design Tool code below this line: +// GUItool: begin automatically generated code +AudioSynthToneSweep tonesweep1; //xy=531.0833129882812,166.08334350585938 +AudioOutputAnalogStereo audioOutput; //xy=727.0833129882812,166.08334350585938 +AudioConnection patchCord1(tonesweep1, 0, audioOutput, 0); +AudioConnection patchCord2(tonesweep1, 0, audioOutput, 1); +// GUItool: end automatically generated code + +float t_ampx = 0.05; // Amplitude +int t_lox = 10; // Low frequency +int t_hix = 22000; // High frequency +float t_timex = 10; // Length of time of the sweep in seconds + + +void setup(void) { + + Serial.begin(9600); + //while (!Serial) ; + delay(3000); + + AudioMemory(6); + + Serial.println("setup done"); + + if(!tonesweep1.play(t_ampx,t_lox,t_hix,t_timex)) { + Serial.println("AudioSynthToneSweep - begin failed"); + while(1); + } + // wait for the sweep to end + while(tonesweep1.isPlaying()); + + // and now reverse the sweep + if(!tonesweep1.play(t_ampx,t_hix,t_lox,t_timex)) { + Serial.println("AudioSynthToneSweep - begin failed"); + while(1); + } + // wait for the sweep to end + while(tonesweep1.isPlaying()); + Serial.println("Done"); +} + +void loop(void){ +} diff --git a/Trellis_M4_Synth_Design/Waveform_Mod_TrellisM4/Waveform_Mod_TrellisM4.ino b/Trellis_M4_Synth_Design/Waveform_Mod_TrellisM4/Waveform_Mod_TrellisM4.ino new file mode 100644 index 00000000..9bac09b1 --- /dev/null +++ b/Trellis_M4_Synth_Design/Waveform_Mod_TrellisM4/Waveform_Mod_TrellisM4.ino @@ -0,0 +1,146 @@ +// Trellis M4 Audio Workshop +// shows how to alter pitch with accelerometer +// Waveform Mod + +#include +#include +#include +#include "Adafruit_NeoTrellisM4.h" +#include + +Adafruit_ADXL343 accel = Adafruit_ADXL343(123, &Wire1); + +// The NeoTrellisM4 object is a keypad and neopixel strip subclass +// that does things like auto-update the NeoPixels and stuff! +Adafruit_NeoTrellisM4 trellis = Adafruit_NeoTrellisM4(); +// Paste your Audio System Design Tool code below this line: +// GUItool: begin automatically generated code +AudioSynthWaveform waveform1; //xy=592.7221984863281,187.38888549804688 +AudioOutputAnalogStereo audioOutput; //xy=777.0833129882812,189.08334350585938 +AudioConnection patchCord1(waveform1, 0, audioOutput, 0); +AudioConnection patchCord2(waveform1, 0, audioOutput, 1); +// GUItool: end automatically generated code + + +int xbend = 64; +int ybend = 64; +int last_xbend = 64; +int last_ybend = 64; + +int count=1; + +void setup() { + trellis.begin(); + trellis.show(); // Initialize w all pixels off + trellis.setBrightness(255); + + if(!accel.begin()) { + Serial.println("No accelerometer found"); + while(1); +} + AudioMemory(10); + // Initialize processor and memory measurements + AudioProcessorUsageMaxReset(); + AudioMemoryUsageMaxReset(); + Serial.begin(115200); + waveform1.begin(WAVEFORM_SAWTOOTH); + delay(1000); +} + + +void loop() { + waveform1.frequency(110 + (ybend * 2)); + waveform1.amplitude(0.05); + wait(5); +} + +void wait(unsigned int milliseconds){ + elapsedMillis msec=0; + while (msec <= milliseconds){ + trellis.tick(); + while(trellis.available()) { + keypadEvent e = trellis.read(); + Serial.print((int)e.bit.KEY); + int keyindex = e.bit.KEY; + if(e.bit.EVENT == KEY_JUST_PRESSED){ + Serial.println(" pressed"); + trellis.setPixelColor(keyindex, Wheel(keyindex * 255 / 32)); // rainbow! + } + else if(e.bit.EVENT == KEY_JUST_RELEASED){ + Serial.println(" released"); + trellis.setPixelColor(keyindex, 0); + } + } + + // Check for accelerometer + sensors_event_t event; + accel.getEvent(&event); + + //check if it's been moved a decent amount + if (abs(event.acceleration.x) < 2.0) { // 2.0 m/s^2 + // don't make any bend unless they've really started moving it + xbend = 64; + } + else { + if (event.acceleration.x > 0) { + xbend = ofMap(event.acceleration.x, 2.0, 10.0, 63, 0, true); // 2 ~ 10 m/s^2 is upward bend + } + else { + xbend = ofMap(event.acceleration.x, -2.0, -10.0, 64, 127, true); // -2 ~ -10 m/s^2 is downward bend + } + } + if (xbend != last_xbend) { + Serial.print("X mod: "); Serial.println(xbend); + last_xbend = xbend; + } + + if (abs(event.acceleration.y) < 2.0) { // 2.0 m/s^2 + ybend = 64; + } + else { + if (event.acceleration.y > 0) { + ybend = ofMap(event.acceleration.y, 2.0, 10.0, 63, 0, true); // 2 ~ 10 m/s^2 is upward bend + } + else { + ybend = ofMap(event.acceleration.y, -2.0, -10.0, 64, 127, true); // -2 ~ -10 m/s^2 is downward bend + } + } + if (ybend != last_ybend) { + Serial.print("Y mod: "); Serial.println(ybend); + last_ybend = ybend; + } + } +} + + +// Input a value 0 to 255 to get a color value. +// The colours are a transition r - g - b - back to r. +uint32_t Wheel(byte WheelPos) { + WheelPos = 255 - WheelPos; + if(WheelPos < 85) { + return Adafruit_NeoPixel::Color(255 - WheelPos * 3, 0, WheelPos * 3); + } + if(WheelPos < 170) { + WheelPos -= 85; + return Adafruit_NeoPixel::Color(0, WheelPos * 3, 255 - WheelPos * 3); + } + WheelPos -= 170; + return Adafruit_NeoPixel::Color(WheelPos * 3, 255 - WheelPos * 3, 0); +} + +// floating point map +float ofMap(float value, float inputMin, float inputMax, float outputMin, float outputMax, bool clamp) { + float outVal = ((value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin); + + if (clamp) { + if (outputMax < outputMin) { + if (outVal < outputMax) outVal = outputMax; + else if (outVal > outputMin) outVal = outputMin; + } else { + if (outVal > outputMax) outVal = outputMax; + else if (outVal < outputMin) outVal = outputMin; + } + } + return outVal; + +}