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
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.