Compare commits
	
		
			No commits in common. "3d13be3b66607c802444427baababfc4722e8a97" and "2d7d7eb1b7590fcc7ed70220c457fec703814c96" have entirely different histories.
		
	
	
		
			3d13be3b66
			...
			2d7d7eb1b7
		
	
		
@ -92,7 +92,7 @@ void setwave(){
 | 
			
		||||
    int val=0;
 | 
			
		||||
 | 
			
		||||
    //saw
 | 
			
		||||
    //val = dacmax * isamp / nsamp;
 | 
			
		||||
    val = dacmax * isamp / nsamp;
 | 
			
		||||
    //val = ( isamp < nsamp / 2 ) ? 0 : dacmax - 1;
 | 
			
		||||
        //sine
 | 
			
		||||
    //val=(sin(phi)+1.0)*dacmax/2;
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@ void setup() {
 | 
			
		||||
  // set compare match register for 1hz increments
 | 
			
		||||
  //OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 | 
			
		||||
  //OCR1A = 7812;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 | 
			
		||||
  OCR1A = 2196;  // about 135bpm?
 | 
			
		||||
  OCR1A = 800;
 | 
			
		||||
  // turn on CTC mode
 | 
			
		||||
  TCCR1B |= (1 << WGM12);
 | 
			
		||||
  // Set CS10 and CS12 bits for 1024 escaler
 | 
			
		||||
@ -63,6 +63,7 @@ void setup() {
 | 
			
		||||
  mcp.setSpeed(800000L);
 | 
			
		||||
  make_tuning(12);
 | 
			
		||||
  note=0;
 | 
			
		||||
  Serial.println("hello");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void make_tuning(int edo) {
 | 
			
		||||
 | 
			
		||||
@ -1,126 +0,0 @@
 | 
			
		||||
//waveform generator
 | 
			
		||||
 | 
			
		||||
// hacked from https://www.instructables.com/Arduino-Waveform-Generator-1/
 | 
			
		||||
 | 
			
		||||
#include <Adafruit_MCP4728.h>
 | 
			
		||||
#include <Wire.h>
 | 
			
		||||
 | 
			
		||||
Adafruit_MCP4728 mcp;
 | 
			
		||||
 | 
			
		||||
#define nsamp 32
 | 
			
		||||
#define dacmax 256
 | 
			
		||||
 | 
			
		||||
const byte nclk = 200; // a guess
 | 
			
		||||
long int freq; //frequency in Hz
 | 
			
		||||
long unsigned int phase;
 | 
			
		||||
long unsigned int phase_inc;
 | 
			
		||||
 | 
			
		||||
int note = 0;
 | 
			
		||||
int gate;
 | 
			
		||||
int decay = 128;
 | 
			
		||||
 | 
			
		||||
float pattern[16];
 | 
			
		||||
 | 
			
		||||
long unsigned int pattern_inc[4];
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  TIMSK0 &= ~_BV(TOIE0); // disable timer0 overflow interrupt
 | 
			
		||||
 | 
			
		||||
  cli();
 | 
			
		||||
 | 
			
		||||
//set timer1 interrupt at 1Hz
 | 
			
		||||
  TCCR1A = 0;// set entire TCCR1A register to 0
 | 
			
		||||
  TCCR1B = 0;// same for TCCR1B
 | 
			
		||||
  TCNT1  = 0;//initialize counter value to 0
 | 
			
		||||
  // set compare match register for 1hz increments
 | 
			
		||||
  OCR1A = 3905;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 | 
			
		||||
  // turn on CTC mode
 | 
			
		||||
  TCCR1B |= (1 << WGM12);
 | 
			
		||||
  // Set CS10 and CS12 bits for 1024 prescaler
 | 
			
		||||
  TCCR1B |= (1 << CS12) | (1 << CS10);  
 | 
			
		||||
  // enable timer compare interrupt
 | 
			
		||||
  TIMSK1 |= (1 << OCIE1A);
 | 
			
		||||
 | 
			
		||||
  sei();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  Serial.begin(115200);
 | 
			
		||||
 | 
			
		||||
  if (!mcp.begin(0x64)) {
 | 
			
		||||
    while (1) {
 | 
			
		||||
      delay(100);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
//  mcp.setSpeed(400000L);
 | 
			
		||||
//  mcp.setSpeed(800000L);
 | 
			
		||||
  mcp.setSpeed(800000L);
 | 
			
		||||
 | 
			
		||||
  freq=440;
 | 
			
		||||
  phase=0;
 | 
			
		||||
  //pattern[0] = 220.0;
 | 
			
		||||
  // pattern[1] = 261.6255653005987;
 | 
			
		||||
  // pattern[2] = 369.9944227116345;
 | 
			
		||||
  // pattern[3] = 391.9954359817495;
 | 
			
		||||
  for( int i = 0; i < 16; i++ ) {
 | 
			
		||||
    pattern[i] = 440 + i * 80;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pattern[1] = 0;
 | 
			
		||||
  pattern[2] = 0;
 | 
			
		||||
 | 
			
		||||
  pattern[4] = 0;
 | 
			
		||||
  pattern[5] = 0;
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
  for( int i = 0; i < 16; i++ ) {
 | 
			
		||||
    pattern_inc[i] = pattern[i] * 975592.231884058;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setwave();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const float pi=3.14159265;
 | 
			
		||||
byte waveform[nsamp];
 | 
			
		||||
byte phaseb = 0;
 | 
			
		||||
void setwave(){
 | 
			
		||||
  for (int isamp=0; isamp<nsamp; ++isamp){
 | 
			
		||||
    float phip=(isamp+0.5)/nsamp;
 | 
			
		||||
    float phi=2*pi*phip;
 | 
			
		||||
    int val=0;
 | 
			
		||||
 | 
			
		||||
    //saw
 | 
			
		||||
    //val = dacmax * isamp / nsamp;
 | 
			
		||||
    //val = ( isamp < nsamp / 2 ) ? 0 : dacmax - 1;
 | 
			
		||||
        //sine
 | 
			
		||||
    val=(sin(phi)+1.0)*dacmax/2;
 | 
			
		||||
    //val=((sin(phi)+0.333*sin(3*phi))/0.943+1)*dacmax/2;
 | 
			
		||||
 | 
			
		||||
    val=max(val,0);
 | 
			
		||||
    val=min(val,dacmax-1);
 | 
			
		||||
    waveform[isamp]=val;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ISR(TIMER1_COMPA_vect){
 | 
			
		||||
  note += 1;
 | 
			
		||||
  if( note > 15 ) {
 | 
			
		||||
    note = 0;
 | 
			
		||||
  }
 | 
			
		||||
  phase_inc = pattern_inc[note];
 | 
			
		||||
  gate = 4095;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void loop() {
 | 
			
		||||
  phase += phase_inc;
 | 
			
		||||
  int redphase = phase >> 27;
 | 
			
		||||
  mcp.fastWrite(waveform[redphase] << 4, gate, 0, 0);
 | 
			
		||||
  if( gate > 0 ) {
 | 
			
		||||
    gate -= decay;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,92 +0,0 @@
 | 
			
		||||
// Triggering shaped envelopes
 | 
			
		||||
 | 
			
		||||
#include <Adafruit_MCP4728.h>
 | 
			
		||||
#include <Wire.h>
 | 
			
		||||
 | 
			
		||||
Adafruit_MCP4728 mcp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
float tuning[37];
 | 
			
		||||
float voltrange = 4.85;  // measured this, probably not accurate
 | 
			
		||||
float octave = 4096.0 / voltrange; // number of DAC steps in an octave
 | 
			
		||||
 | 
			
		||||
//bool gates[] = { true, false, true, false, true, false, false, true };
 | 
			
		||||
 | 
			
		||||
bool gates[] = { true, false, false, false, true, false, false, false };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int freqs[8];
 | 
			
		||||
 | 
			
		||||
int lpattern = 8;
 | 
			
		||||
int note = 0;
 | 
			
		||||
 | 
			
		||||
bool trigger = false;
 | 
			
		||||
long t0 = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
 | 
			
		||||
  cli();
 | 
			
		||||
 | 
			
		||||
//set timer1 interrupt at 1Hz
 | 
			
		||||
  TCCR1A = 0;// set entire TCCR1A register to 0
 | 
			
		||||
  TCCR1B = 0;// same for TCCR1B
 | 
			
		||||
  TCNT1  = 0;//initialize counter value to 0
 | 
			
		||||
  // set compare match register for 1hz increments
 | 
			
		||||
  //OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 | 
			
		||||
  //OCR1A = 7812;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 | 
			
		||||
  OCR1A = 10000;
 | 
			
		||||
  // turn on CTC mode
 | 
			
		||||
  TCCR1B |= (1 << WGM12);
 | 
			
		||||
  // Set CS10 and CS12 bits for 1024 escaler
 | 
			
		||||
  TCCR1B |= (1 << CS12) | (1 << CS10);  
 | 
			
		||||
  // enable timer compare interrupt
 | 
			
		||||
  TIMSK1 |= (1 << OCIE1A);
 | 
			
		||||
 | 
			
		||||
  sei();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if (!mcp.begin(0x64)) {
 | 
			
		||||
    while (1) {
 | 
			
		||||
      delay(100);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  randomSeed(analogRead(A0));
 | 
			
		||||
  mcp.setSpeed(800000L);
 | 
			
		||||
 | 
			
		||||
  for( int i = 0; i < 8; i++ ) {
 | 
			
		||||
    freqs[i] = random(10, 450);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  trigger = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ISR(TIMER1_COMPA_vect){ // called once every note
 | 
			
		||||
  trigger = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void loop() {
 | 
			
		||||
  long now = millis();
 | 
			
		||||
  float f1;
 | 
			
		||||
  int gate;
 | 
			
		||||
  long freq;
 | 
			
		||||
  if( trigger ) {
 | 
			
		||||
    t0 = now;
 | 
			
		||||
    trigger = false;
 | 
			
		||||
    freq = freqs[note];
 | 
			
		||||
    gate = gates[note];
 | 
			
		||||
    note++;
 | 
			
		||||
    if( note == lpattern ) {
 | 
			
		||||
      note = 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  f1 = 0.5 - 0.5 * sin((float)(now - t0) / (float)1000.0);
 | 
			
		||||
  mcp.setChannelValue(MCP4728_CHANNEL_A, round(4095.0 * f1));
 | 
			
		||||
  mcp.setChannelValue(MCP4728_CHANNEL_B, gate ? 4095 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,167 +0,0 @@
 | 
			
		||||
// Better sequencer which uses interrupts
 | 
			
		||||
 | 
			
		||||
#include <Adafruit_MCP4728.h>
 | 
			
		||||
#include <Wire.h>
 | 
			
		||||
 | 
			
		||||
Adafruit_MCP4728 mcp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
float tuning[37];
 | 
			
		||||
float voltrange = 4.85;  // measured this, probably not accurate
 | 
			
		||||
float octave = 4096.0 / voltrange; // number of DAC steps in an octave
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int note = 0;
 | 
			
		||||
 | 
			
		||||
// kick
 | 
			
		||||
// int pitch[] = { 8, -1, -1, -1, 8,-1, -1, -1, 8,-1, -1, -1, 8, -1, -1, 8, 
 | 
			
		||||
//                 8, -1, -1, -1, 8,-1, -1, -1, -1,-1, 8, -1, -1, 8, -1, 8,
 | 
			
		||||
// };
 | 
			
		||||
// float dur[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 | 
			
		||||
// 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// hi hat
 | 
			
		||||
// int pitch[] = { 8, 8, -1, 8, 8, 8, -1, 8, 8,8 , -1, 8, 8, 8, -1, 8, 
 | 
			
		||||
//                 8, 8, -1, 8, 8, 8, -1, 8, 8,8 , -1, 8, 8, 8, 8, 8, 
 | 
			
		||||
// };
 | 
			
		||||
// float dur[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 | 
			
		||||
// 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, };
 | 
			
		||||
 | 
			
		||||
// bass triggers
 | 
			
		||||
 | 
			
		||||
int pitch[] = { 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 
 | 
			
		||||
                1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, };
 | 
			
		||||
                
 | 
			
		||||
float dur[] = { 8, 1, 1,1,  1,1,1,1,  1,1,1,1, 4, 1,1,1,
 | 
			
		||||
8, 1, 1,1,  1,1,1,1,  1,1,1,1, 4, 1,1,1,};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int phrase = 32;
 | 
			
		||||
 | 
			
		||||
int s;
 | 
			
		||||
int bpm = 110;
 | 
			
		||||
int beat_m = 100; // fix me coordinate with timer code
 | 
			
		||||
bool noteon = false;
 | 
			
		||||
int beat = false;
 | 
			
		||||
long notestart, notedur;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  Serial.begin(115200);
 | 
			
		||||
 | 
			
		||||
  float freqint = 60.0 / (float)bpm;
 | 
			
		||||
 | 
			
		||||
  int ocr = round(16 * 10 ^ 6 / (1024.0 * freqint * 16)) - 1
 | 
			
		||||
 | 
			
		||||
  Serial.println(ocr);
 | 
			
		||||
 | 
			
		||||
  if( ocr < 65536 ) {
 | 
			
		||||
 | 
			
		||||
    cli();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //set timer1 interrupt at 1Hz
 | 
			
		||||
    TCCR1A = 0;// set entire TCCR1A register to 0
 | 
			
		||||
    TCCR1B = 0;// same for TCCR1B
 | 
			
		||||
    TCNT1  = 0;//initialize counter value to 0
 | 
			
		||||
    // set compare match register for 1hz increments
 | 
			
		||||
    //OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 | 
			
		||||
    //OCR1A = 7812;// = (16*10^6) / (1*1024) - 1 (must be <65536)
 | 
			
		||||
    OCR1A = ocr; 
 | 
			
		||||
    // turn on CTC mode
 | 
			
		||||
    TCCR1B |= (1 << WGM12);
 | 
			
		||||
    // Set CS10 and CS12 bits for 1024 escaler
 | 
			
		||||
    TCCR1B |= (1 << CS12) | (1 << CS10);  
 | 
			
		||||
    // enable timer compare interrupt
 | 
			
		||||
    TIMSK1 |= (1 << OCIE1A);
 | 
			
		||||
 | 
			
		||||
    sei();
 | 
			
		||||
 | 
			
		||||
  } else {
 | 
			
		||||
    Serial.println("BPM out of range")
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!mcp.begin(0x64)) {
 | 
			
		||||
    while (1) {
 | 
			
		||||
      delay(100);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // randomSeed(analogRead(A0));
 | 
			
		||||
  mcp.setSpeed(800000L);
 | 
			
		||||
  make_tuning(7);
 | 
			
		||||
  note=0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void make_tuning(int edo) {
 | 
			
		||||
  float n0 = 0;
 | 
			
		||||
  float edof = (float)edo;
 | 
			
		||||
  for( int i = 0; i < 37; i++ ) {
 | 
			
		||||
      tuning[i] = round(n0 + octave * (float)i / edof);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float mod_f(int x) {
 | 
			
		||||
  return 1 - sq((float)x / 1000.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ISR(TIMER1_COMPA_vect){ // called once every note
 | 
			
		||||
  beat = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void loop() {
 | 
			
		||||
  float mod;
 | 
			
		||||
  int o;
 | 
			
		||||
  long now = millis();
 | 
			
		||||
  if( beat ) {
 | 
			
		||||
    beat = false;
 | 
			
		||||
    if( pitch[s] > -1 ) {
 | 
			
		||||
      notestart = millis();
 | 
			
		||||
      notedur = round(beat_m * dur[s]);
 | 
			
		||||
      noteOn(pitch[s]);
 | 
			
		||||
      noteon = true;
 | 
			
		||||
    }
 | 
			
		||||
    s += 1;
 | 
			
		||||
    if( s == phrase ) {
 | 
			
		||||
      s = 0;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if( noteon ) {
 | 
			
		||||
        mod = mod_f(now - notestart);
 | 
			
		||||
        o = round(mod * 4095.0);
 | 
			
		||||
        if( o > 4095 ) {
 | 
			
		||||
          o = 4095;
 | 
			
		||||
        }
 | 
			
		||||
        if( o < 0 ) {
 | 
			
		||||
          o = 0;
 | 
			
		||||
        } 
 | 
			
		||||
        mcp.setChannelValue(MCP4728_CHANNEL_C, o);
 | 
			
		||||
      if( now - notestart > notedur ) {
 | 
			
		||||
        noteOff();
 | 
			
		||||
        noteon = false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void noteOn(int note) {
 | 
			
		||||
  if( note > -1 ) {
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_A, tuning[note]);
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_B, 4095);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void noteOff() {
 | 
			
		||||
    Serial.println("off");
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_B, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,159 +0,0 @@
 | 
			
		||||
// Better sequencer which uses interrupts
 | 
			
		||||
 | 
			
		||||
#include <Adafruit_MCP4728.h>
 | 
			
		||||
#include <Wire.h>
 | 
			
		||||
 | 
			
		||||
Adafruit_MCP4728 mcp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
float tuning[37];
 | 
			
		||||
float voltrange = 4.85;  // measured this, probably not accurate
 | 
			
		||||
float octave = 4096.0 / voltrange; // number of DAC steps in an octave
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// melody
 | 
			
		||||
// int pitch[] = { 1,3,7,2,3,4,3,4,3,4,6,7,3,4,3,1,3, 5, 9, 4, 5, 6, 5, 6, 5, 6, 8, 9, 5, 6, 5, 3};
 | 
			
		||||
// float dur[] = { 0.1,0.00, 0.1, 0.05, 0.1,0.05, 0.05, 0.05,
 | 
			
		||||
// 0.1,0.05, 0.1, 0.05, 0.1,0.05, 0.05, 0.05,
 | 
			
		||||
// 0.1,0.05, 0.1, 0.05, 0.1,0.05, 0.05, 0.05,
 | 
			
		||||
// 0.1,0.05, 0.1, 0.05, 0.1,0.05, 0.05, 0.05,};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int pitch[] = { 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  2, -1, -1, -1,
 | 
			
		||||
-1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1,-1, -1, -1, -1, };
 | 
			
		||||
int dur[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
 | 
			
		||||
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  };
 | 
			
		||||
 | 
			
		||||
int note = 0;
 | 
			
		||||
int phrase = 32;
 | 
			
		||||
 | 
			
		||||
int s;
 | 
			
		||||
int bpm = 110;
 | 
			
		||||
float beat_s = 60.0 / (float)bpm;
 | 
			
		||||
float beat_m = 1000.0 * beat_s; 
 | 
			
		||||
bool noteon = false;
 | 
			
		||||
int beat = false;
 | 
			
		||||
long notestart, notedur, barstart;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  Serial.begin(115200);
 | 
			
		||||
 | 
			
		||||
  float freqint = 60.0 / (float)bpm;
 | 
			
		||||
 | 
			
		||||
  int ocr = round(16000000.0 / (1024.0 * freqint * 16)) - 1;
 | 
			
		||||
  Serial.println(ocr);
 | 
			
		||||
  if( ocr < 65536 ) {
 | 
			
		||||
 | 
			
		||||
    cli();
 | 
			
		||||
 | 
			
		||||
    TCCR1A = 0;// set entire TCCR1A register to 0
 | 
			
		||||
    TCCR1B = 0;// same for TCCR1B
 | 
			
		||||
    TCNT1  = 0;//initialize counter value to 0
 | 
			
		||||
    OCR1A = ocr; 
 | 
			
		||||
    // turn on CTC mode
 | 
			
		||||
    TCCR1B |= (1 << WGM12);
 | 
			
		||||
    // Set CS10 and CS12 bits for 1024 escaler
 | 
			
		||||
    TCCR1B |= (1 << CS12) | (1 << CS10);  
 | 
			
		||||
    // enable timer compare interrupt
 | 
			
		||||
    TIMSK1 |= (1 << OCIE1A);
 | 
			
		||||
 | 
			
		||||
    sei();
 | 
			
		||||
 | 
			
		||||
  } else {
 | 
			
		||||
    Serial.println("BPM out of range");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!mcp.begin(0x64)) {
 | 
			
		||||
    while (1) {
 | 
			
		||||
      delay(100);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // randomSeed(analogRead(A0));
 | 
			
		||||
  mcp.setSpeed(800000L);
 | 
			
		||||
  make_tuning(7);
 | 
			
		||||
  note=0;
 | 
			
		||||
  barstart=millis();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void make_tuning(int edo) {
 | 
			
		||||
  float n0 = 0;
 | 
			
		||||
  float edof = (float)edo;
 | 
			
		||||
  for( int i = 0; i < 37; i++ ) {
 | 
			
		||||
      tuning[i] = round(n0 + octave * (float)i / edof);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// mod_note argument is milliseconds from the start of last note
 | 
			
		||||
float mod_note(int x) {
 | 
			
		||||
  return 1 - sq((float)x / 1000.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mod_note argument is milliseconds from the start of this bar
 | 
			
		||||
float mod_bar(int x) {
 | 
			
		||||
  return 0.5 + 0.5 * sin((float)x / (beat_m * 2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void set_mod(MCP4728_channel_t channel, float v) {
 | 
			
		||||
  int o;
 | 
			
		||||
  o = round(v * 4095.0);
 | 
			
		||||
  if( o > 4095 ) {
 | 
			
		||||
    o = 4095;
 | 
			
		||||
  }
 | 
			
		||||
  if( o < 0 ) {
 | 
			
		||||
    o = 0;
 | 
			
		||||
  } 
 | 
			
		||||
  mcp.setChannelValue(channel, o);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ISR(TIMER1_COMPA_vect){ // called once every beat
 | 
			
		||||
  beat = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void loop() {
 | 
			
		||||
  float mod;
 | 
			
		||||
  int o;
 | 
			
		||||
  long now = millis();
 | 
			
		||||
  if( beat ) {
 | 
			
		||||
    beat = false;
 | 
			
		||||
    if( pitch[s] > -1 ) {
 | 
			
		||||
      notestart = millis();
 | 
			
		||||
      notedur = round(beat_m * dur[s]);
 | 
			
		||||
      noteOn(pitch[s]);
 | 
			
		||||
      noteon = true;
 | 
			
		||||
    }
 | 
			
		||||
    s += 1;
 | 
			
		||||
    if( s == phrase ) {
 | 
			
		||||
      s = 0;
 | 
			
		||||
      barstart = notestart;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if( noteon ) {
 | 
			
		||||
        set_mod(MCP4728_CHANNEL_C, mod_note(now - notestart));
 | 
			
		||||
      if( now - notestart > notedur ) {
 | 
			
		||||
        noteOff();
 | 
			
		||||
        noteon = false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    set_mod(MCP4728_CHANNEL_D, mod_bar(now - barstart));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void noteOn(int note) {
 | 
			
		||||
  if( note > -1 ) {
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_A, tuning[note]);
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_B, 4095);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void noteOff() {
 | 
			
		||||
    Serial.println("off");
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_B, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,160 +0,0 @@
 | 
			
		||||
// Better sequencer which uses interrupts
 | 
			
		||||
 | 
			
		||||
#include <Adafruit_MCP4728.h>
 | 
			
		||||
#include <Wire.h>
 | 
			
		||||
 | 
			
		||||
Adafruit_MCP4728 mcp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
float tuning[37];
 | 
			
		||||
float voltrange = 4.85;  // measured this, probably not accurate
 | 
			
		||||
float octave = 4096.0 / voltrange; // number of DAC steps in an octave
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// melody
 | 
			
		||||
 | 
			
		||||
// int pitch[] = { 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 | 
			
		||||
// -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1,2, -1, -1, -1, };
 | 
			
		||||
// int dur[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
			
		||||
//             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,  };
 | 
			
		||||
 | 
			
		||||
// hi hat
 | 
			
		||||
 | 
			
		||||
int pitch[] = { 1, 2, 3,2, 4, 2,5, 0,1, 2, 3,2, 4, 2,5, 0,1, 2, 3,2, 4, 2,5, 0,1, 2, 3,2, 4, 2,5, 0, };
 | 
			
		||||
int dur[] = { 0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int note = 0;
 | 
			
		||||
int phrase = 32;
 | 
			
		||||
 | 
			
		||||
int s;
 | 
			
		||||
int bpm = 80;
 | 
			
		||||
float beat_s = 60.0 / (float)bpm;
 | 
			
		||||
float beat_m = 1000.0 * beat_s; 
 | 
			
		||||
bool noteon = false;
 | 
			
		||||
int beat = false;
 | 
			
		||||
long notestart, notedur, barstart;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  Serial.begin(115200);
 | 
			
		||||
 | 
			
		||||
  float freqint = 60.0 / (float)bpm;
 | 
			
		||||
 | 
			
		||||
  int ocr = round(16000000.0 / (1024.0 * freqint * 16)) - 1;
 | 
			
		||||
  Serial.println(ocr);
 | 
			
		||||
  if( ocr < 65536 ) {
 | 
			
		||||
 | 
			
		||||
    cli();
 | 
			
		||||
 | 
			
		||||
    TCCR1A = 0;// set entire TCCR1A register to 0
 | 
			
		||||
    TCCR1B = 0;// same for TCCR1B
 | 
			
		||||
    TCNT1  = 0;//initialize counter value to 0
 | 
			
		||||
    OCR1A = ocr; 
 | 
			
		||||
    // turn on CTC mode
 | 
			
		||||
    TCCR1B |= (1 << WGM12);
 | 
			
		||||
    // Set CS10 and CS12 bits for 1024 escaler
 | 
			
		||||
    TCCR1B |= (1 << CS12) | (1 << CS10);  
 | 
			
		||||
    // enable timer compare interrupt
 | 
			
		||||
    TIMSK1 |= (1 << OCIE1A);
 | 
			
		||||
 | 
			
		||||
    sei();
 | 
			
		||||
 | 
			
		||||
  } else {
 | 
			
		||||
    Serial.println("BPM out of range");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!mcp.begin(0x64)) {
 | 
			
		||||
    while (1) {
 | 
			
		||||
      delay(100);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // randomSeed(analogRead(A0));
 | 
			
		||||
  mcp.setSpeed(800000L);
 | 
			
		||||
  make_tuning(12);
 | 
			
		||||
  note=0;
 | 
			
		||||
  barstart=millis();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void make_tuning(int edo) {
 | 
			
		||||
  float n0 = 0;
 | 
			
		||||
  float edof = (float)edo;
 | 
			
		||||
  for( int i = 0; i < 37; i++ ) {
 | 
			
		||||
      tuning[i] = round(n0 + octave * (float)i / edof);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// mod_note argument is milliseconds from the start of last note
 | 
			
		||||
float mod_note(int x) {
 | 
			
		||||
  float xb = x / (0.2 * beat_m);
 | 
			
		||||
  return 0.5 + 0.5 * xb * (xb - 1) * ( xb - 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mod_note argument is milliseconds from the start of this bar
 | 
			
		||||
float mod_bar(int x) {
 | 
			
		||||
  return 0.5 + 0.5 * sin((float)x / (beat_m * 2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void set_mod(MCP4728_channel_t channel, float v) {
 | 
			
		||||
  int o;
 | 
			
		||||
  o = round(v * 4095.0);
 | 
			
		||||
  if( o > 4095 ) {
 | 
			
		||||
    o = 4095;
 | 
			
		||||
  }
 | 
			
		||||
  if( o < 0 ) {
 | 
			
		||||
    o = 0;
 | 
			
		||||
  } 
 | 
			
		||||
  mcp.setChannelValue(channel, o);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ISR(TIMER1_COMPA_vect){ // called once every beat
 | 
			
		||||
  beat = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void loop() {
 | 
			
		||||
  float mod;
 | 
			
		||||
  int o;
 | 
			
		||||
  long now = millis();
 | 
			
		||||
  if( beat ) {
 | 
			
		||||
    beat = false;
 | 
			
		||||
    if( pitch[s] > -1 ) {
 | 
			
		||||
      notestart = millis();
 | 
			
		||||
      notedur = round(beat_m * dur[s]);
 | 
			
		||||
      noteOn(pitch[s]);
 | 
			
		||||
      noteon = true;
 | 
			
		||||
    }
 | 
			
		||||
    s += 1;
 | 
			
		||||
    if( s == phrase ) {
 | 
			
		||||
      s = 0;
 | 
			
		||||
      barstart = notestart;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if( noteon ) {
 | 
			
		||||
        set_mod(MCP4728_CHANNEL_C, mod_note(now - notestart));
 | 
			
		||||
      if( now - notestart > notedur ) {
 | 
			
		||||
        noteOff();
 | 
			
		||||
        noteon = false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    set_mod(MCP4728_CHANNEL_D, mod_bar(now - barstart));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void noteOn(int note) {
 | 
			
		||||
  if( note > -1 ) {
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_A, tuning[note]);
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_B, 4095);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void noteOff() {
 | 
			
		||||
    Serial.println("off");
 | 
			
		||||
    mcp.setChannelValue(MCP4728_CHANNEL_B, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -95,9 +95,3 @@ Using the random-note-clouds technique from the 8th but this time picking
 | 
			
		||||
pitches from a hexany tuning, running it four times and drenching it in
 | 
			
		||||
reverb
 | 
			
		||||
 | 
			
		||||
### 20 Fibomod
 | 
			
		||||
 | 
			
		||||
Using the Fibonacci series modulo n, also known as the (Pisano period)[https://en.wikipedia.org/wiki/Pisano_period], as a wavetable, and incrementing n for each note in the sequence
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								TODO.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								TODO.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
## TODO 
 | 
			
		||||
 6 October
 | 
			
		||||
 | 
			
		||||
s 6 - Wavetable updates
 | 
			
		||||
m 7 - Change a sequence while it's playing
 | 
			
		||||
t 8 - Sound clouds
 | 
			
		||||
w 9 - 7TET groove
 | 
			
		||||
t 10 - Drum pattern
 | 
			
		||||
f 11 - Scratchy karplus-strong beats
 | 
			
		||||
s 12 - sequencer 2
 | 
			
		||||
s 13 - accidental FM synth
 | 
			
		||||
m 14 - slow dank
 | 
			
		||||
t 15 - rattatat
 | 
			
		||||
w 16 - 
 | 
			
		||||
t 17
 | 
			
		||||
f 18
 | 
			
		||||
s 19
 | 
			
		||||
s 20
 | 
			
		||||
m 21 
 | 
			
		||||
t 22
 | 
			
		||||
w 23
 | 
			
		||||
t 24
 | 
			
		||||
f 25
 | 
			
		||||
s 26
 | 
			
		||||
s 27
 | 
			
		||||
m 28
 | 
			
		||||
t 29
 | 
			
		||||
w 30
 | 
			
		||||
t 31
 | 
			
		||||
 | 
			
		||||
More ideas
 | 
			
		||||
 | 
			
		||||
deliberate FM synthesis
 | 
			
		||||
KR to AR modulation and back
 | 
			
		||||
Envelopes
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user