Hey guys!
I tried to do as much of this on my own since I notice sometimes the same questions will get asked multiple times. I've read a ton of them and actually got pretty far with a device that actually works sort of but when this major issue came up I decided to call in a professional. Any help is majorly appreciated!
So what I need is a device that plays 2 tracks, loaded up with samples pulled from the sd card and simply looped (don't worry i'm NOT asking about seamless looping here). Simple controls really, each 'deck' (this is basically like a set of cdj's on a DJ setup with limited controls over the decks so i use the terminology) would have 2 buttons, one for skipping to the next track and one for going to the previous track, then one global button (rather than on each deck this could be a single button controlling both) to 'restart' both tracks playing once i've found the 2 samples i want. Obviously more buttons would be greatly useful and i could do pots, led, all kinds of stuff but just getting minimal stuff going for now. I've gotten most of the buttons in place then something huge came up. it plays the entire first sample once and THEN starts playing the second one. I need them both to start at the same time (exactly the same if possible which up till now i've been ok with a slight delay).
Wouldn't the best solution be to just use a queue where I could get the tracks lined up and THEN play them? Also, this code has it to where when i scroll through the samples i'm actually listening to each one. that's great but at some point i'd like to simply skip to the track i want and THEN just press a 'PLAY' button for both tracks to trigger then. can add a display later to see the tracks but for now i don't mind simply pressing the seek button a couple times by memory. I'm using a teensy 4 with the audio shield for that version and here is my jumbled code.if anyone has any ideas I appreciate your consideration big time this has been quite the discovery process for me!
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
AudioPlaySdWav playSdWav2;
AudioPlaySdWav playSdWav1;
AudioMixer4 mixer1;
AudioMixer4 mixer2;
AudioOutputI2S i2s1;
AudioConnection patchCord1(playSdWav2, 0, mixer2, 0);
AudioConnection patchCord2(playSdWav2, 1, mixer1, 1);
AudioConnection patchCord3(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord4(playSdWav1, 1, mixer2, 1);
AudioConnection patchCord5(mixer1, 0, i2s1, 0);
AudioConnection patchCord6(mixer2, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
Bounce button0 = Bounce(0, 15); //this is the GLOBAL AUTO STOP & START
Bounce button1 = Bounce(1, 15); //DECK 1 SKIP TO NEXT TRACK
Bounce button2 = Bounce(2, 15); //DECK 1 GO BACK TO PREVIOUS TRACK
Bounce button3 = Bounce(3, 15); //DECK 2 SKIP TO NEXT TRACK
Bounce button4 = Bounce(4, 15); //DECK 2 GO BACK TO PREVIOUS TRACK
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 11
#define SDCARD_SCK_PIN 13
void setup() {
Serial.begin(9600);
AudioMemory(8);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
pinMode(0, INPUT_PULLUP); //STOP ALL & START OVER AS IS
pinMode(1, INPUT_PULLUP); //DECK 1 SKIP
pinMode(2, INPUT_PULLUP); //DECK 1 REWIND
pinMode(3, INPUT_PULLUP); //DECK 2 SKIP
pinMode(4, INPUT_PULLUP); //DECK 2 REWIND
delay(1000);
}
int filenumber = 0; //track playing on deck1
int filenumber1 = 0; //track playing on deck2
const char * filelist[4] = {
"DRUM87B1.WAV", "DRUM87B3.WAV", "800001.WAV", "800003.WAV"
}; //DECK 1 TRACKS THESE WILL ALL BE DRUM BEATS FOR THE MOST PART
const char * filelist1[4] = {
"BASS87A#.WAV", "BASS87E1.WAV", "80000006.WAV", "80000008.WAV"
}; //DECK 2 TRACKS ALL OF THE MUSICAL SAMPLES
void loop() {
//DECK 1 PLAYER, TOOK OUT THE FUNCTION THAT WENT THROUGH ALL THE TRACKS SO IT WOULD JUST LOOP WHICHEVER TRACK WAS SELECTED AT THE MOMENT
if (playSdWav1.isPlaying() == false) {
const char *filename = filelist[filenumber];
Serial.print("Start playing ");
Serial.println(filename);
playSdWav1.play(filename);
delay(10);
}
//DECK 2 PLAYER, I'VE DONE THIS WHERE BOTH DECKS HAVE THE SAME SAMPLE AND THEY ARE CLOSE ENOUGH IN SYNC THAT THEY PRETTY MUCH SOUND LIKE ONE SAMPLE FOR ABOUT 20 LOOPS BEFORE GETTING THAT 'PHASER' SOUND
if (playSdWav2.isPlaying() == false) {
const char *filename1 = filelist1[filenumber1];
playSdWav2.play(filename1);
}
//HERE ARE THE BUTTON SELECTORS - FIRST ONE SIMPLY STOPS ALL AND STARTS FROM THE BEGINNING AT WHICHEVER SAMPLE IS SELECTED
button0.update();
if (button0.fallingEdge()) {
playSdWav1.stop();
playSdWav2.stop();
}
//DECK 1 SKIP TO NEXT TRACK UNTIL LAST TRACK IT GOES BACK TO FIRST TRACK
button1.update();
if (button1.fallingEdge()) {
playSdWav1.stop();
filenumber = filenumber + 1;
if (filenumber >= 3) filenumber = filenumber - 3;
}
//DECK 1 PREVIOUS TRACK UNTIL THE BEGINNING THEN IT GOES TO THE LAST TRACK AGAIN
button2.update();
if (button2.fallingEdge()) {
playSdWav1.stop();
filenumber = filenumber - 1;
if (filenumber < 0) filenumber = filenumber + 3;
}
//DECK 2 SKIP TO NEXT TRACK TILL THE END WHEN IT GOES BACK TO BEGINNING
button3.update();
if (button3.fallingEdge()) {
playSdWav2.stop();
filenumber1 = filenumber1 + 1;
if (filenumber1 >= 3) filenumber1 = filenumber1 - 3;
}
//DECK 2 PREVIOUS TRACK TILL THE BEGINNING WHEN IT CYCLES BACK TO LAST TRACK
button4.update();
if (button4.fallingEdge()) {
playSdWav2.stop();
filenumber1 = filenumber1 - 1;
if (filenumber1 < 0) filenumber1 = filenumber1 + 3;
}
}
I tried to do as much of this on my own since I notice sometimes the same questions will get asked multiple times. I've read a ton of them and actually got pretty far with a device that actually works sort of but when this major issue came up I decided to call in a professional. Any help is majorly appreciated!
So what I need is a device that plays 2 tracks, loaded up with samples pulled from the sd card and simply looped (don't worry i'm NOT asking about seamless looping here). Simple controls really, each 'deck' (this is basically like a set of cdj's on a DJ setup with limited controls over the decks so i use the terminology) would have 2 buttons, one for skipping to the next track and one for going to the previous track, then one global button (rather than on each deck this could be a single button controlling both) to 'restart' both tracks playing once i've found the 2 samples i want. Obviously more buttons would be greatly useful and i could do pots, led, all kinds of stuff but just getting minimal stuff going for now. I've gotten most of the buttons in place then something huge came up. it plays the entire first sample once and THEN starts playing the second one. I need them both to start at the same time (exactly the same if possible which up till now i've been ok with a slight delay).
Wouldn't the best solution be to just use a queue where I could get the tracks lined up and THEN play them? Also, this code has it to where when i scroll through the samples i'm actually listening to each one. that's great but at some point i'd like to simply skip to the track i want and THEN just press a 'PLAY' button for both tracks to trigger then. can add a display later to see the tracks but for now i don't mind simply pressing the seek button a couple times by memory. I'm using a teensy 4 with the audio shield for that version and here is my jumbled code.if anyone has any ideas I appreciate your consideration big time this has been quite the discovery process for me!
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
AudioPlaySdWav playSdWav2;
AudioPlaySdWav playSdWav1;
AudioMixer4 mixer1;
AudioMixer4 mixer2;
AudioOutputI2S i2s1;
AudioConnection patchCord1(playSdWav2, 0, mixer2, 0);
AudioConnection patchCord2(playSdWav2, 1, mixer1, 1);
AudioConnection patchCord3(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord4(playSdWav1, 1, mixer2, 1);
AudioConnection patchCord5(mixer1, 0, i2s1, 0);
AudioConnection patchCord6(mixer2, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
Bounce button0 = Bounce(0, 15); //this is the GLOBAL AUTO STOP & START
Bounce button1 = Bounce(1, 15); //DECK 1 SKIP TO NEXT TRACK
Bounce button2 = Bounce(2, 15); //DECK 1 GO BACK TO PREVIOUS TRACK
Bounce button3 = Bounce(3, 15); //DECK 2 SKIP TO NEXT TRACK
Bounce button4 = Bounce(4, 15); //DECK 2 GO BACK TO PREVIOUS TRACK
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 11
#define SDCARD_SCK_PIN 13
void setup() {
Serial.begin(9600);
AudioMemory(8);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
pinMode(0, INPUT_PULLUP); //STOP ALL & START OVER AS IS
pinMode(1, INPUT_PULLUP); //DECK 1 SKIP
pinMode(2, INPUT_PULLUP); //DECK 1 REWIND
pinMode(3, INPUT_PULLUP); //DECK 2 SKIP
pinMode(4, INPUT_PULLUP); //DECK 2 REWIND
delay(1000);
}
int filenumber = 0; //track playing on deck1
int filenumber1 = 0; //track playing on deck2
const char * filelist[4] = {
"DRUM87B1.WAV", "DRUM87B3.WAV", "800001.WAV", "800003.WAV"
}; //DECK 1 TRACKS THESE WILL ALL BE DRUM BEATS FOR THE MOST PART
const char * filelist1[4] = {
"BASS87A#.WAV", "BASS87E1.WAV", "80000006.WAV", "80000008.WAV"
}; //DECK 2 TRACKS ALL OF THE MUSICAL SAMPLES
void loop() {
//DECK 1 PLAYER, TOOK OUT THE FUNCTION THAT WENT THROUGH ALL THE TRACKS SO IT WOULD JUST LOOP WHICHEVER TRACK WAS SELECTED AT THE MOMENT
if (playSdWav1.isPlaying() == false) {
const char *filename = filelist[filenumber];
Serial.print("Start playing ");
Serial.println(filename);
playSdWav1.play(filename);
delay(10);
}
//DECK 2 PLAYER, I'VE DONE THIS WHERE BOTH DECKS HAVE THE SAME SAMPLE AND THEY ARE CLOSE ENOUGH IN SYNC THAT THEY PRETTY MUCH SOUND LIKE ONE SAMPLE FOR ABOUT 20 LOOPS BEFORE GETTING THAT 'PHASER' SOUND
if (playSdWav2.isPlaying() == false) {
const char *filename1 = filelist1[filenumber1];
playSdWav2.play(filename1);
}
//HERE ARE THE BUTTON SELECTORS - FIRST ONE SIMPLY STOPS ALL AND STARTS FROM THE BEGINNING AT WHICHEVER SAMPLE IS SELECTED
button0.update();
if (button0.fallingEdge()) {
playSdWav1.stop();
playSdWav2.stop();
}
//DECK 1 SKIP TO NEXT TRACK UNTIL LAST TRACK IT GOES BACK TO FIRST TRACK
button1.update();
if (button1.fallingEdge()) {
playSdWav1.stop();
filenumber = filenumber + 1;
if (filenumber >= 3) filenumber = filenumber - 3;
}
//DECK 1 PREVIOUS TRACK UNTIL THE BEGINNING THEN IT GOES TO THE LAST TRACK AGAIN
button2.update();
if (button2.fallingEdge()) {
playSdWav1.stop();
filenumber = filenumber - 1;
if (filenumber < 0) filenumber = filenumber + 3;
}
//DECK 2 SKIP TO NEXT TRACK TILL THE END WHEN IT GOES BACK TO BEGINNING
button3.update();
if (button3.fallingEdge()) {
playSdWav2.stop();
filenumber1 = filenumber1 + 1;
if (filenumber1 >= 3) filenumber1 = filenumber1 - 3;
}
//DECK 2 PREVIOUS TRACK TILL THE BEGINNING WHEN IT CYCLES BACK TO LAST TRACK
button4.update();
if (button4.fallingEdge()) {
playSdWav2.stop();
filenumber1 = filenumber1 - 1;
if (filenumber1 < 0) filenumber1 = filenumber1 + 3;
}
}