diff --git a/07DynamicSequences/07DynamicSequences.ino b/07DynamicSequences/07DynamicSequences.ino new file mode 100644 index 0000000..e117aac --- /dev/null +++ b/07DynamicSequences/07DynamicSequences.ino @@ -0,0 +1,113 @@ +// Basic demo for configuring the MCP4728 4-Channel 12-bit I2C DAC +#include +#include + +Adafruit_MCP4728 mcp; + + +// 1 3 5 7 hexany log2 +float hexany[] = { 0.12928301694496647, 0.32192809488736235, 0.3923174227787603, 0.5849625007211562, 0.8073549220576041, 0.9068905956085185 }; +float tuning[18]; +int pitch[] = { 4, 3, 2, 1, 2, 3, 4, 3 }; +float dur[] = { 2, 2, 2, 2, 2, 2, 2, 2 }; +float gate = 0.5; +int bpm = 135; +int phrase = 8; +float beat_s = 60.0 / (float)bpm; +int beat_m = round(1000.0 * beat_s); +float voltrange = 4.85; // measured this, probably not accurate +float octave = 4096.0 / voltrange; // number of DAC steps in an octave +float mod_b = 3.141592653589793 / 4.0; + + +int s; +bool noteon = false; +long play_t; +long release_t; +long last_t; +long init_t; + + +void setup(void) { + Serial.begin(115200); + while (!Serial) + delay(10); // will pause Zero, Leonardo, etc until serial console opens + + if (!mcp.begin(0x64)) { + Serial.println("Failed to find MCP4728 chip"); + while (1) { + delay(10); + } + Serial.println("MCP4728 initialised"); + } + + mcp.setChannelValue(MCP4728_CHANNEL_B, 0); + + float n0 = 0; + for( int o = 0; o < 3; o++ ) { + for( int i = 0; i < 18; i++ ) { + tuning[o * 6 + i] = round(n0 + octave * (o + hexany[i])); + } + } + + s = 0; + release_t = 0; + play_t = 0; + last_t = millis(); + init_t = last_t; +} + + +void make_tuning() { + float n0 = 0; + for( int i = 0; i < 18; i++ ) { + tuning[i] = round(n0 + octave * hexany[i]); + } + +} + + +void loop() { + long now = millis(); + if( noteon ) { + if( now - last_t > release_t ) { + noteOff(); + last_t = now; + play_t = round(beat_m * dur[s] * (1.0 - gate)); + noteon = false; + s += 1; + if( s == phrase ) { + s = 0; + updatePhrase(); + } + } + } else { + if( now - last_t > play_t ) { + noteOn(pitch[s]); + last_t = now; + release_t = round(beat_m * dur[s] * gate); + noteon = true; + } + } + // // sychronise this better + // long mod_t = (now - init_t); + // float mod = 0.5 + 0.5 * sin(mod_b * (float)mod_t / (float)beat_m); + // mcp.setChannelValue(MCP4728_CHANNEL_C, round(4095.0 * mod)); +} + + +void updatePhrase() { + int n = random(phrase); + pitch[n] = random(6); +} + +void noteOn(int note) { + if( note > -1 ) { + mcp.setChannelValue(MCP4728_CHANNEL_A, tuning[note]); + mcp.setChannelValue(MCP4728_CHANNEL_B, 4095); + } +} + +void noteOff() { + mcp.setChannelValue(MCP4728_CHANNEL_B, 0); +}