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

    Kal12/10/2021 at 00:51 0 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?
    }

  • log update update

    Kal12/04/2021 at 19:22 0 comments

    add serial feedback or, f'it, put some 555's oscillating for output

  • Nervous system

    Kal12/04/2021 at 03:37 0 comments

    The '121s are across some male header. That shouldn't short anything that shouldn't be, right? Then i've jumped the address pins of two of them to what should be the right points to make them enumerate right. All the soldering looks good to me, i don't think the hardware's bad.

    I threw this code together but the thing just whines. I don't think i'm crazy with the timing, i think it should be audible if it's recognizing input. Maybe the '121s draw too much power, i didn't check that.

    #include <Wire.h>
    #include "Adafruit_MPR121.h"
    const uint8_t freq1 = 300;
    const uint8_t freq2 = 400;
    const uint8_t freq3 = 500;
    const uint8_t numberoffrets = 12;
    unsigned long t;
    unsigned long oldmicros;
    int string1[freq1];
    int string2[freq2];
    int string3[freq3];
    uint8_t c;
    Adafruit_MPR121 cap1 = Adafruit_MPR121();
    Adafruit_MPR121 cap2 = Adafruit_MPR121();
    Adafruit_MPR121 cap3 = Adafruit_MPR121();
    
    void setup() {
      delay(100);
      pinMode(1, OUTPUT);
      Wire.begin();
      if (!cap1.begin(0x5a)) while(1);
      if (!cap2.begin(0x5b)) while(1);
      if (!cap3.begin(0x5c)) while(1);
      //cap2.begin(0x5b);
      //cap3.begin(0x5c);
      //wire.begin(0x5A);
      //wire.begin(0x5B);
      //wire.begin(0x5C);
    }
    
    void loop() {
      t = micros();
      if (t > oldmicros+1000) {
          for (uint8_t fret=1; fret < numberoffrets; fret++){
            if (cap1.touched() & (1 << fret)) {for(uint8_t c=1; c < freq1/2; c++){string1[c] = (random(2^16)-2^8);}}
            if (cap2.touched() & (1 << fret)) {for(uint8_t c=1; c < freq2/2; c++){string2[c] = (random(2^16)-2^8);}}
            if (cap3.touched() & (1 << fret)) {for(uint8_t c=1; c < freq3/2; c++){string3[c] = (random(2^16)-2^8);}}
          oldmicros=0;}
      for(uint8_t c=1; c<freq1; c++){string1[1] = (string1[2]+string1[3])/2);}
      for(uint8_t c=1; c<freq2; c++){string2[1] = (string2[2]+string2[3])/2);}
      for(uint8_t c=1; c<freq3; c++){string3[1] = (string3[2]+string3[3])/2);}
      analogWrite(1, string1[1]+string2[1]+string3[1] / 3);
    }

    It should be an implementation of the Karplus-Strong algorithm but i'm staring at the void. Next step is serial feedback or the funner parts of hardware.