Close

not doing what i said i would BUT starting w/much better code

A project log for Musical Instrument with mock-strings

a noisemaker in the style of a musical instrument or vice versa, with touch inputs to an arduino

KalKal 12/10/2021 at 00:510 Comments

I'm less confident this is a Karplus-Strong but more confident it'll do something like what i want. (SAVE THAT it's nothing like specific to the actual hardware)

// boneheaded implementation of karplus-strong alg.:

// 3 "strings" are basically a pointer (p) into a register
// the pointer advances once every so-many micros
// look up what "so-many" is based on which-if-any fret is held down

// usually the entry at p gets overridden by the average of p+1 and p+2 and then output
// on pluck, start instead overriding by the average of p+1, p+2 and a random value and do that for a while.
// half a cycle? man, i dunno. i'm starting w/just plucks plucked

// seeeduino xiao has 32KB RAM: 10k of 1B samples in 3 arrays leaves plenty of overhead
// but would require a better meaurement than micros() to get through a whole register in 1s/freq

// "physical" parameters of the system:
uint8_t registerA[1000], pluckedA;
unsigned int pointerA, durationA;
uint8_t registerB[1000], pluckedB;
unsigned int pointerB, durationB;
uint8_t registerC[1000], pluckedC;
unsigned int pointerC, durationC;

//time and timing:
unsigned long t, startA, startB, startC;

//pin assignation: ENTIRELY FAKE
const uint8_t pluckA = 1;
const uint8_t pluckC = 2;
const uint8_t pluckB = 3;
const uint8_t out = 4;

int c; //counting variable

void setup() {
  durationA = 3034;
  durationB = 4050;
  durationC = 5102;
  // ugh, duration math should go behind an interrupt probs
  // oh, interrupt pins don't wanna be common/short maybs
  pointerA = 1; pointerB = 1; pointerC = 1;
}

void loop() {
  // find out where we are, see if it's where we 'posed'a be:
  t = micros();
  if (pointerA > 999) {
    pointerA = 1;
    startA = t;
    pluckedA--;
  } else {
    while ((t - startA)>(pointerA * (durationA / 1000))) pointerA++; // if that pointer's behind where it should be increment it until it's not
    // where t-startA is time passed, pA*(dA/1000) is what the pointer says is time passed
    // and the wrong variable names are way easier to read
  }
  if (pointerB > 999) {
    pointerB = 1;
    startB = t;
    pluckedB--;
  } else {
    while ((t - startB)>(pointerB * (durationB / 1000))) pointerB++; // ditto this'n
  }
  if (pointerC > 999) {
    pointerC = 1;
    startC = t;
    pluckedC--;
  } else {
    while ((t - startC)>(pointerC * (durationC / 1000))) pointerC++; // ditto that'n
  }

  // read pins and add pluckage if necc.:
  // ((will never fill >50% in a row, will often fill >50% with gaps -- UNWANTED BEHAVIOR?))
  if ((!pluckedA) & (!digitalRead(pluckA))) {
    pluckedA = 2;
    for (c = 1; c < 500; c++) {
      if ((pointerA + c) <= 1000) {registerA[pointerA + c] = ((registerA[pointerA + c] + random(256)) / 2);}
      else {registerA[pointerA + c - 999] = ((registerA[pointerA + c - 999] + random(256)) / 2);}
    }
  }
  if ((!pluckedB) & (!digitalRead(pluckB))) {
    pluckedB = 2;
    for (c = 1; c < 500; c++) {
      if ((pointerB + c) <= 1000) {registerB[pointerB + c] = ((registerB[pointerB + c] + random(256)) / 2);}
      else {registerB[pointerB + c - 999] = ((registerB[pointerB + c - 999] + random(256)) / 2);}
    }
  }
  if ((!pluckedC) & (!digitalRead(pluckC))) {
    pluckedC = 2;
    for (c = 1; c < 500; c++) {
      if ((pointerC + c) <= 1000) {registerC[pointerC + c] = ((registerC[pointerC + c] + random(256)) / 2);}
      else {registerC[pointerC + c - 999] = ((registerC[pointerC + c - 999] + random(256)) / 2);}
    }
  }

  // do the actual work:
  if (pointerA = 1000) {registerA[1000] = ((registerA[1000] + registerA[1]) / 2);}
  else {registerA[pointerA] = ((registerA[pointerA] + registerA[pointerA + 1]) / 2);}
  if (pointerB = 1000) {registerB[1000] = ((registerB[1000] + registerB[1]) / 2);}
  else {registerB[pointerB] = ((registerB[pointerB] + registerB[pointerB + 1]) / 2);}
  if (pointerC = 1000) {registerC[1000] = ((registerC[1000] + registerC[1]) / 2);}
  else {registerC[pointerC] = ((registerC[pointerC] + registerC[pointerC + 1]) / 2);}
  analogWrite(out, ((registerA[pointerA] + registerB[pointerB] + registerC[pointerC]) / 3)); // is averaging these correct?
}

Discussions