Hi Takumi!
Sorry to revive an old thread, but I’m back on the looper project after quite a while, and I’m running into some issues that seemed to have popped up since the new version of the Arduino IDE… My looper sketch has evolved quite far in the last year, but for some reason, I’m back at the start, able to pass audio, but with no actual looper functionality.
It’s quite messy (as the parameters of the project changed quite a bit over time), but hopefully we can get to the bottom of it!
Here’s how it stands currently…
#include "DaisyDuino.h"
#define MAX_SIZE 4800000 // 5 minutes of floats at 48 khz
static DaisyHardware petal;
bool first = true; // first loop (sets length)
bool rec = false; // currently recording
bool play = false; // currently playing
int posL = 0;
int posR = 0;
int posU = 0;
float DSY_SDRAM_BSS bufL[MAX_SIZE];
float DSY_SDRAM_BSS bufR[MAX_SIZE];
float DSY_SDRAM_BSS bufU[MAX_SIZE];
int mod = MAX_SIZE;
int len = 0;
int mute = 1;
int clr = 1;
float wet;
float mon;
bool full = false;
bool start = false;
bool out = false;
bool res = false;
bool flash = false;
bool fastflash = false;
bool undo = false;
bool redo = false;
bool hold = false;
bool flatten = false;
bool stack = false;
bool dub = false;
bool overdub = false;
bool cont = false;
bool wipe = false;
bool dHold = false;
bool wHold = false;
uint32_t Time = 0;
uint32_t lastTime = 0;
uint32_t counter;
const long flashInt = 500;
unsigned long previousMillis = 0;
unsigned long rectime = 0;
const long fastflashInt = 500;
unsigned long fastpreviousMillis = 0;
uint8_t LED_R;
uint8_t LED_G;
uint8_t switchMode;
int togState;
unsigned long fswPrevMillis = 0;
unsigned long fswTime = 0;
bool maintain = false;
bool press = false;
void ResetBuffer();
void Controls();
void NextSamples(float &output, float **in, size_t i);
static void AudioCallback(float **in, float **out, size_t size) {
float outputL = 0;
float outputR = 0;
Controls();
for (size_t i = 0; i < size; i++) {
NextSamples(outputL, outputR, in, i);
// left and right outs
out[0][i] = outputL * 2;
out[1][i] = outputR * 2; //COMMENT OUT FOR MONO
}
}
void setup() {
// initialize petal hardware and oscillator daisysp module
petal = DAISY.init(DAISY_PETAL, AUDIO_SR_48K);
ResetBuffer();
rec = false;
play = false;
Serial.begin(9600);
// start callback
DAISY.begin(AudioCallback);
//Declarations
LED_R = 5; // SEED pin 6
pinMode(LED_R, OUTPUT);
LED_G = 6; // SEED pin 7
pinMode(LED_G, OUTPUT);
switchMode = 3; // SEED pin 4
pinMode(switchMode, INPUT_PULLUP);
}
void loop() {
// Serial.print(rectime);
// Serial.print(",");
// Serial.print(cont);
Serial.println(cont);
togState = digitalRead(switchMode);
if(togState == LOW) {
flatten = true;
stack = false;
}
if(togState == HIGH) {
flatten = false;
stack = true;
}
counter = Time - lastTime;
if (counter > 0 && counter <= 500) {
dub = true;
}
if(counter > 500){
counter = 0;
dub = false;
}
//undo/redo flash
unsigned long fastcurrentMillis = System::GetNow();
if(fastcurrentMillis - fastpreviousMillis >= fastflashInt) {
fastpreviousMillis = fastcurrentMillis;
if(fastflash == LOW) {
fastflash = HIGH;
}
else{
fastflash = LOW;
}
}
//flash LED
unsigned long currentMillis = System::GetNow();
if(currentMillis - previousMillis >= flashInt) {
previousMillis = currentMillis;
if(flash == LOW) {
flash = HIGH;
}
else{
flash = LOW;
}
}
// LED Control
if(play&&rec) {
digitalWrite(LED_R, HIGH);
digitalWrite(LED_G, LOW);
}
if(play&&!rec) {
digitalWrite(LED_R, LOW);
if(posL <= 4800) {
digitalWrite(LED_G, LOW);
}
else {
digitalWrite(LED_G, HIGH);
}
}
if(!play) {
if(flash == true && res == true) {
digitalWrite(LED_R, HIGH);
digitalWrite(LED_G, LOW);
}
else{
digitalWrite(LED_R, LOW);
digitalWrite(LED_G, LOW);
}
}
}
// Resets the buffer
void ResetBuffer() {
play = false;
rec = false;
first = true;
undo = false;
redo = false;
dub = false;
overdub = false;
press = false;
full = false;
start = false;
out = false;
cont = false;
wipe = false;
mute = 1;
posL = 0;
posR = 0;
posU = 0;
len = 0;
rectime = 0;
for (int i = 0; i < mod; i++) {
bufL[i] = 0;
bufR[i] = 0;
bufU[i] = 0;
}
mod = MAX_SIZE;
}
void UpdateButtons() {
unsigned long fswCurrentMillis = System::GetNow();
switch (first) {
case true:
if(petal.buttons[0].RisingEdge()) {
if (first && rec) {
first = false;
mod = len;
len = 0;
}
res = true;
play = true;
rec = !rec;
full = false;
wipe = true;
}
break;
case false:
if (petal.buttons[0].RisingEdge()){
Timer();
fswPrevMillis = fswCurrentMillis;
fswTime = 0;
}
if(petal.buttons[0].FallingEdge()) {
fswTime = fswCurrentMillis - fswPrevMillis;
if(fswTime <= 10) {
press = false;
maintain = false;
}
if(fswTime >= 11 && fswTime <= 300) {
press = true;
maintain = false;
}
if(fswTime > 301) {
maintain = true;
press = false;
}
}
break;
}
if (press){
if(!play && res) {
play = true;
rec = !rec;
dub = false;
}
res = true;
play = true;
rec = !rec;
press = false;
wipe = false;
if(rec == false) {
full = true;
}
// Timer();
}
if (dub) {
play = false;
rec = false;
posL = 0;
posR = 0;
posU = 0;
rectime = 0;
start = false;
out = false;
cont = false;
}
if (petal.buttons[0].TimeHeldMs() >= 1000 && res && !play && dHold == false){
clr = 0;
dHold = true;
ResetBuffer();
res = false;
Timer();
}
if(dHold && petal.buttons[0].FallingEdge()) {
clr = 1;
dHold = false;
}
if (petal.buttons[0].TimeHeldMs() >= 1000 && wipe && play && wHold == false){
clr = 0;
wHold = true;
ResetBuffer();
res = false;
Timer();
}
if(wHold && petal.buttons[0].FallingEdge()) {
clr = 1;
wHold = false;
}
if (petal.buttons[0].TimeHeldMs() >= 1000 && res && play && hold == false){
mute = 0;
undo = !undo;
rec = false;
hold = true;
}
if(hold && petal.buttons[0].FallingEdge()) {
mute = 1;
hold = false;
}
}
// Deals with analog controls
void Controls() {
petal.ProcessAllControls();
wet = petal.controls[1].Value();
UpdateButtons();
}
void mixBuffer(int posR, int posL) {
bufL[posL] = bufL[posL] + bufR[posR];
bufR[posR] = 0;
}
void WriteBuffer_R(float **in, size_t i) {
bufR[posR] = bufR[posR] + in[0][i];
}
void WriteBuffer_L(float **in, size_t i) {
bufL[posL] = bufL[posL] + in[0][i];
if (first) {
len++;
}
}
void NextSamples(float &outputL,float &outputR, float **in, size_t i) {
if(rec && first){
WriteBuffer_L(in, i);
}
if(rec && !first) {
rectime++;
if(stack) {
WriteBuffer_R(in, i);
full = true;
}
if(flatten) {
if(!cont) {
mixBuffer(posL, posR);
}
WriteBuffer_R(in, i);
}
/*bufL[posL] = bufL[posL] + bufR[posR];
bufR[posR] = 0;*/
if(undo){
for (int i = 0; i < mod; i++) {
bufR[i] = 0;
bufU[i] = 0;
}
undo = false;
full = false;
}
}
//STEREO OUT
outputL = ((bufL[posL]* clr) * wet);
outputR = (bufR[posR]* mute) * wet;
//MONO OUT
//outputL = ((bufL[posL] * clr) * wet) + ((bufR[posR]* mute) * wet);
//outputR = 0;
// automatic looptime
if (len >= MAX_SIZE) {
first = false;
rec = !rec;
play = !play;
mod = MAX_SIZE;
len = 0;
}
if (play) {
if(petal.buttons[0].FallingEdge() && !rec&& !first){
out = true;
start = false;
rectime = 0;
cont = false;
}
if(petal.buttons[0].FallingEdge() && rec && !first) {
out = false;
start = true;
}
if(rectime > mod) {
cont = true;
}
posL++;
posL %= mod;
posR++;
posR %= mod;
posU++;
posU %= mod;
if(undo) {
bufU[posU] = bufU[posU] + bufR[posR];
bufR[posR] = bufR[posR] * 0;
full = false;
}
if(!undo && !first){
bufR[posR] = bufR[posR] + bufU[posU];
bufU[posU] = bufU[posU] * 0;
full = true;
}
}
if (!rec) {
outputL = outputL + in[0][i];
//outputR = outputR * wet + in[0][i];
}
}
void Timer(){
lastTime = Time;
Time = System::GetNow();
}
/*if(flatten) {
bufL[posL] = bufL[posL] + bufR[posR];
bufR[posR] = 0;
}*/
This was all before the STM32CUBEProgrammer was available as a programming option, so I don’t know if that has something to do with it? I’ll follow up with my programming options (if i can figure out how…) 