From 71fd9e319a51f5d3d49fa4b1c23d08c5ff4d3ab0 Mon Sep 17 00:00:00 2001 From: Mike Lynch Date: Wed, 27 Dec 2023 15:16:37 +1100 Subject: [PATCH] Made time calculations all be in integer microseconds --- Xmas/Xmas.ino | 71 +++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/Xmas/Xmas.ino b/Xmas/Xmas.ino index dd24a99..0799ee9 100644 --- a/Xmas/Xmas.ino +++ b/Xmas/Xmas.ino @@ -35,7 +35,7 @@ the absolute start time should include a count-in int m1[] = { 0, 2, 4, 5, 7, 9, 11, 12 }; -int s1[] = { 0, 3, 5, 7, 9, 11, 13, 15 }; +int s1[] = { 0, 2, 4, 6, 8, 10, 12, 14 }; float d1[] = { 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5 }; int m2[] = { 0, 4, 7, 12, 0, 4, 7, 12, 0, 4, 7, 12, 0, 4, 7, 12 }; int s2[] = { 0, 1 , 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; @@ -45,12 +45,14 @@ float d2[] = { 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 float gate = 0.5; int bpm = 180; float beat_s = 60.0 / (float)bpm; -int beat_m = round(1000.0 * beat_s); +int beat = round(1000.0 * beat_s); // count_in = number of beats since t0 to wait before we startt playing // repeat = number of beats to repeat - could be computed from the sequence data -long count_in_m = 4 * beat_m; +// From here on, all times are in milliseconds to head off floating point errors + +long count_in = 4 * beat; int repeat = 16; @@ -112,31 +114,49 @@ void setup(void) { seq2.start = s2; seq2.len = sizeof(m2) / sizeof(m2[0]); + times_to_ms(seq1); + times_to_ms(seq2); + } +void times_to_ms(sequencer& seq) { + for( int i = 0; i < seq.len; i++ ) { + seq.start[i] *= beat; + seq.duration[i] = (float)beat * seq.duration[i]; + } +} + + void loop() { long now = millis(); - long beat_int = (now - start_time - count_in_m) % (beat_m * repeat); - float beat = (float)(beat_int) / (float)beat_m; - runSequencer(seq1, now, beat); - runSequencer(seq2, now, beat); + long t = now - start_time; + long beats = -1; + if( t >= count_in ) { + beats = (t - count_in) % (beat * repeat); + runSequencer(seq1, t, beats); + runSequencer(seq2, t, beats); + } } -void runSequencer(sequencer& seq, long now, float beat) { - if( seq.s < seq.len - 1 ) { - if( beat > (float)seq.start[seq.s + 1] ) { - seq.s += 1; - seq.rel = now + round((float)beat_m * seq.duration[seq.s]); - if( seq.melody[seq.s] > -1 ) { - mcp.setChannelValue(seq.pitch, tuning[seq.melody[seq.s]]); - mcp.setChannelValue(seq.gate, 4095); - } - seq.playing = 1; - if( seq.s == seq.len - 1 ) { - seq.s = -1; - } +void runSequencer(sequencer& seq, long now, long beats) { + int next = seq.s + 1; + int start; + if( next > seq.len - 1 ) { + seq.s = -1; + next = 0; + return; // don't start the loop yet + } else { + start = seq.start[next]; + } + if( beats >= start ) { + seq.s = next; + seq.rel = now + seq.duration[seq.s]; + if( seq.melody[seq.s] > -1 ) { + mcp.setChannelValue(seq.pitch, tuning[seq.melody[seq.s]]); + mcp.setChannelValue(seq.gate, 4095); } + seq.playing = 1; } if( seq.playing ) { if( now > seq.rel ) { @@ -146,14 +166,3 @@ void runSequencer(sequencer& seq, long now, float beat) { } } - -// void noteOn(sequencer& seq, int note) { -// if( note > -1 ) { -// mcp.setChannelValue(seq.pitch, tuning[note]); -// mcp.setChannelValue(seq.gate, 4095); -// } -// } - -// void noteOff(sequencer& seq) { -// mcp.setChannelValue(seq.gate, 0); -// }