///////////////////////////////////
// copy the Design Tool code here
///////////////////////////////////
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioPlaySdWav playSdWav1; //xy=77,26
AudioPlaySdWav playSdWav2; //xy=79,67
AudioPlaySdRaw playSdRaw1; //xy=79,158
AudioSynthSimpleDrum drum2; //xy=81,355
AudioSynthSimpleDrum drum4; //xy=85,474
AudioSynthSimpleDrum drum3; //xy=87,401
AudioSynthSimpleDrum drum1; //xy=88,283
AudioPlaySdRaw playSdRaw2; //xy=95,220
AudioAmplifier amp6; //xy=235,413
AudioAmplifier amp4; //xy=252,371
AudioAmplifier amp5; //xy=255,471
AudioMixer4 mixer1; //xy=258,35
AudioMixer4 mixer2; //xy=263,99
AudioAmplifier amp1; //xy=264,168
AudioAmplifier amp3; //xy=270,281
AudioAmplifier amp2; //xy=293,219
AudioEffectFreeverb freeverb3; //xy=548,139
AudioEffectFreeverb freeverb4; //xy=558,210
AudioEffectFreeverb freeverb2; //xy=575,73
AudioEffectFreeverb freeverb5; //xy=576,267
AudioEffectFreeverb freeverb1; //xy=584,36
AudioEffectFreeverb freeverb6; //xy=591,352
AudioEffectFreeverb freeverb7; //xy=597,431
AudioEffectFreeverb freeverb8; //xy=599,506
AudioMixer4 mixer3; //xy=757,178
AudioMixer4 mixer4; //xy=788,272
AudioMixer4 masterMix; //xy=954,203
AudioOutputI2S i2s1; //xy=994,343
AudioConnection patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord2(playSdWav1, 1, mixer1, 1);
AudioConnection patchCord3(playSdWav2, 0, mixer2, 0);
AudioConnection patchCord4(playSdWav2, 1, mixer2, 1);
AudioConnection patchCord5(playSdRaw1, amp1);
AudioConnection patchCord6(drum2, amp4);
AudioConnection patchCord7(drum4, amp5);
AudioConnection patchCord8(drum3, amp6);
AudioConnection patchCord9(drum1, amp3);
AudioConnection patchCord10(playSdRaw2, amp2);
AudioConnection patchCord11(amp6, freeverb7);
AudioConnection patchCord12(amp4, freeverb6);
AudioConnection patchCord13(amp5, freeverb8);
AudioConnection patchCord14(mixer1, freeverb1);
AudioConnection patchCord15(mixer2, freeverb2);
AudioConnection patchCord16(amp1, freeverb3);
AudioConnection patchCord17(amp3, freeverb5);
AudioConnection patchCord18(amp2, freeverb4);
AudioConnection patchCord19(freeverb3, 0, mixer3, 2);
AudioConnection patchCord20(freeverb4, 0, mixer3, 3);
AudioConnection patchCord21(freeverb2, 0, mixer3, 1);
AudioConnection patchCord22(freeverb5, 0, mixer4, 0);
AudioConnection patchCord23(freeverb1, 0, mixer3, 0);
AudioConnection patchCord24(freeverb6, 0, mixer4, 1);
AudioConnection patchCord25(freeverb7, 0, mixer4, 2);
AudioConnection patchCord26(freeverb8, 0, mixer4, 3);
AudioConnection patchCord27(mixer3, 0, masterMix, 0);
AudioConnection patchCord28(mixer4, 0, masterMix, 3);
AudioConnection patchCord29(masterMix, 0, i2s1, 0);
AudioConnection patchCord30(masterMix, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=836,584
// GUItool: end automatically generated code
AudioPlaySdWav *playSdWav[4]={&playSdWav1, &playSdWav2 };
AudioPlaySdRaw *playSdRaw[4]={&playSdRaw1, &playSdRaw2 };
AudioSynthSimpleDrum *drum[4]={&drum1,&drum2,&drum3,&drum4};
#include <ILI9341_t3.h>
#include <font_Arial.h> // from ILI9341_t3
#define TFT_DC 9
#define TFT_CS 10
#define TFT_RST 255 // 255 = unused, connect to 3.3V
#define TFT_MOSI 11
#define TFT_SCLK 13
#define TFT_MISO 12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
int bpm=120;
int rawObjects=0;
int wavObjects=0;
int synthObjects=0;
#define WHOLENOTE 4
#define HALFNOTE 2
#define QUARTERNOTE 1
#define EIGHTHNOTE .5
#define SIXTEENTHNOTE .25
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else // __ARM__
extern char *__brkval;
#endif // __arm__
int freeMemory() {
char top;
#ifdef __arm__
return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
return &top - __brkval;
#else // __arm__
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif // __arm__
}
//*******************************************************************************************************************
//*******************************************************************************************************************
//* Sample Class
//*******************************************************************************************************************
//*******************************************************************************************************************
class Sample{
protected:
float noteType; // i.e., what percentage of bpm is this note (e.g., a quarternote is 1 bpm, an eigthnote is .5)
int pattern=0;
int patternPosition=0;
int patternLength=0;
int isInverted=0;
int id;
elapsedMillis change;
public:
void setup(){
}
void changePattern(int beats, int rests){
patternLength=beats+rests;
pattern=findBeats(beats,rests);
printPattern(pattern,isInverted, patternLength);
}
//*******************************************************************************************************************
// Main Sample Loop
//*******************************************************************************************************************
void loop(){
if(change>=(noteType*(60000/bpm))){
// e.g., an eighthnote at 120 bpm should play every 250 milliseconds, which is 4 times a secon or 240 times a minute
change=0;
if(nowIsTheTimeToParty(patternPosition, pattern, patternLength, isInverted)){
thenLetsParty();
}
patternPosition++;
if(patternPosition>(patternLength-1)) patternPosition=0;
}
}
int nowIsTheTimeToParty(int pos, int pattern, int len, int isInverted){
/* So, pattern 1101001, pos 0 = 1, pos 1=1, pos 2=0
* for pos 2, shift it left length-pos (5) = 11 and then just BITWISE AND 1 */
int p=pattern>>((len-1)-pos);
// Serial.println(p,BIN);
int x=p&1;
if(!isInverted) x=x^1; // Got confused with the inverting, so if it *isn't* inverted, we flip the bit here
return x;
// See, I'm told that bitwise AND return 0 if the rightmost digit is 0, and 1 if 1. I'm told.
}
virtual void thenLetsParty(){}
int findBeats(int beats, int rests){
Serial.print(beats); Serial.print(" beats and "); Serial.print(rests); Serial.println(" rests.");
Serial.print("This pattern is called '");
Serial.print(findName(beats,rests));
Serial.println("'.");
isInverted=0;
patternLength=beats+rests;
int large=rests;
int sm=beats;
if(beats>rests){
isInverted=1;
large=beats;
sm=rests;
}
int bigArray[large];
int smallArray[sm];
//Make two arrays, a big one and a little. Fill the big one with the specified number of beats or rests (1 or )
//Depending on which one there is more of.
int r=0;
for(int i=0;i<large;i++){
bigArray[i]=1;
if(r<sm) smallArray[r]=0;
r++;
}
// Serial.println("here we go");
// The euclid function ultimately squeezes the two arrays together according to Euclids GCF algorhythm
// MaxRuns (starting at 20) prevents the recursive function from looping forever.
int x=euclid(beats,rests,bigArray, smallArray, 20);
// Serial.print(x,BIN);
// Serial.println(" is what I get in findPattern");
return x;
}
int euclid(int beats, int rests, int bigArray[], int smallArray[], int maxRuns){
int big=beats;
int small=rests;
if(beats<rests){
big=rests;
small=beats;
}
int remainder=big - small;
// Ok, we have an array, bigArray, of arrays of 1s and 0s
// And we have a smaller array,
int newBigArray[small];
for(int i=0;i<small;i++){
// Start with bigArray=[1][1][1] or whatever and smallArray=[0][0][0]
// and end with newBigArray=[10][10][10] somehow
newBigArray[i]=bigArray[i];
int t=smallArray[i];
while(t>1){
newBigArray[i]=newBigArray[i]<<1;
t=t>>1;
}
newBigArray[i]=newBigArray[i]<<1;
newBigArray[i]=newBigArray[i] | smallArray[i];
}
if(remainder==0 || maxRuns<=0) {
for(int i=1;i<(small);i++){
// Starting with the element in [1]
int t=newBigArray[i];
// We go through and count down the number of digits, shifting [i]
while(t>1){
newBigArray[0]=newBigArray[0]<<1;
t=t>>1;
}
newBigArray[0]=newBigArray[0]<<1;
newBigArray[0]=newBigArray[0] | newBigArray[i];
}
return newBigArray[0];
}
else{
int newSmallArray[remainder];
for(int i=0;i<remainder;i++){
newSmallArray[i]=bigArray[small+i];
}
if(remainder>small){ //i.e., if small array is larger than bigArray
return euclid(remainder, small, newSmallArray, newBigArray, maxRuns-1);
}
else{
return euclid(small, remainder, newBigArray, newSmallArray, maxRuns-1);
}
}
}
void printPattern(int p, int inverted, int pl){
const char* a=".";
const char *b="X";
if(inverted){
a="X";
b=".";
}
int j=p;
for(int i=pl-1;i>=0;i--){
// Shift the pattern to the left by its length-1
j=p>>i;
if(j&1) Serial.print(a);
else Serial.print(b);
}
Serial.println(" <------ Ta da!!!");
}
const char* findName(int a, int b){
b=b+a;
if(a==4 && b==12) return "Fandango";
else if(a==2 && b==3) return "Swing Tumbao";
else if(a==2 && b==5) return "Khafif-e-ramal";
else if(a==3 && b==4) return "Cumbia";
else if(a==3 && b==5) return "Khalif-e-ramal";
else if(a==3 && b==7) return "Ruchenitza";
else if(a==3 && b==8) return "Tresillo";
else return "Something cool.";
}
};
//*******************************************************************************************************************
//*******************************************************************************************************************
// SD SAMPLE!!!
//*******************************************************************************************************************
//*******************************************************************************************************************
class SDSample : public Sample{
File currentDir;
File currentSample;
const char *sampleName;
char fullSamplePath[50];
int isItRaw;
public:
void setup(const char *dn,const char *sn,float n, int beats, int rests, int raw=0){
sampleName=sn;
noteType=n;
changePattern(beats, rests);
currentDir=loadDir(dn);
currentSample=loadSample(sn);
if(raw){
isItRaw=1;
id=rawObjects;
rawObjects++;
}
else{
wavObjects++;
id=wavObjects;
}
}
/************************************************************************************************************************************
* loadDir()
************************************************************************************************************************************/
File loadDir(const char* dir){
Serial.println(dir);
File myFile;
myFile=SD.open(dir);
Serial.print("Directory: ");Serial.println(myFile.name());
return myFile;
}
/************************************************************************************************************************************
* loadSample()
************************************************************************************************************************************/
File loadSample(const char* sampleName){
File myFile;
sprintf(fullSamplePath, "/%s/%s",currentDir.name(),sampleName);
Serial.print("Name 1: ");Serial.println(fullSamplePath);
myFile=SD.open(fullSamplePath);
if(! myFile){
Serial.println("Can't open file");
return myFile;
}
else{
return myFile;
}
}
//*******************************************************************************************************************
// Play SDSample
//*******************************************************************************************************************
void thenLetsParty(){
if(isItRaw){
delay(30);
playSdRaw[id]->play(fullSamplePath);
}
else playSdWav[id]->play(fullSamplePath);
}
};
//*******************************************************************************************************************
//*******************************************************************************************************************
// Synth Drum!!!
//*******************************************************************************************************************
//*******************************************************************************************************************
class SynthDrum : public Sample{
public:
void setup(int f, int l, float m, float p, float n, int beats, int rests){
noteType=n;
changePattern(beats, rests);
id=synthObjects;
synthObjects++;
drum[id]->frequency(f);
drum[id]->length(l);
drum[id]->secondMix(m);
drum[id]->pitchMod(p);
}
//*******************************************************************************************************************
// Play synth drum
//*******************************************************************************************************************
void thenLetsParty(){
Serial.println("pARTY!");
drum[id]->noteOn();
}
};
//*******************************************************************************************************************
//*******************************************************************************************************************
//* Main Program Space
//*******************************************************************************************************************
//*******************************************************************************************************************
SDSample sample1;
SDSample sample2;
SDSample sample3;
SDSample sample4;
SynthDrum synthD1;
SynthDrum synthD2;
SynthDrum synthD3;
SynthDrum synthD4;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(500);
tft.begin();
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_YELLOW);
tft.setFont(Arial_24);
//tft.setTextSize(3);
tft.setCursor(40, 8);
tft.println("DEADBEEF");
AudioMemory(20);
sgtl5000_1.enable();
sgtl5000_1.volume(0.8);
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);
}
}
delay(1000);
float vol=.65;
mixer1.gain(0, vol*.5);
mixer1.gain(1, vol*.5);
mixer2.gain(0, vol*.5);
mixer2.gain(1, vol*.5);
amp1.gain(vol);
amp2.gain(vol);
amp3.gain(vol);
amp4.gain(vol);
amp5.gain(vol);
amp6.gain(vol);
mixer3.gain(0, vol);
mixer3.gain(1, vol);
mixer3.gain(2, vol);
mixer3.gain(3, vol);
mixer4.gain(0, vol);
mixer4.gain(1, vol);
mixer3.gain(2, vol);
mixer3.gain(3, vol);
masterMix.gain(0, 1);
masterMix.gain(3, 1);
freeverb1.roomsize(.5);
freeverb2.roomsize(0);
freeverb3.roomsize(0);
freeverb4.roomsize(0);
freeverb5.roomsize(.5);
freeverb6.roomsize(0);
freeverb7.roomsize(0);
freeverb8.roomsize(0);
freeverb1.damping(.75);
freeverb2.damping(0);
freeverb3.damping(0);
freeverb4.damping(0);
freeverb5.damping(.75);
freeverb6.damping(0);
freeverb7.damping(0);
freeverb8.damping(0);
sample1.setup("D_808", "asia.wav", HALFNOTE,5,3);
// sample2.setup("D_808", "damn.wav", EIGHTHNOTE,1,1);
sample3.setup("D_808", "icehat.wav", SIXTEENTHNOTE,2,1);
// sample4.setup("D_808", "asia.wav", QUARTERNOTE,5,3);
synthD1.setup(120, 500, 0.55, 1, QUARTERNOTE, 5,7);
synthD2.setup(60, 250, 0.25, .5, QUARTERNOTE, 3,5);
synthD3.setup(440, 500, 1, 1, EIGHTHNOTE, 3,2);
synthD4.setup(440, 500, 1, 1, QUARTERNOTE, 1,7);
}
elapsedMillis msec;
void loop() {
// Mixer 1
sample1.loop();
// sample2.loop();
// Mixer 2
//sample3.loop();
// sample4.loop();
// Mixer 3
// sample5.loop();
// sample6.loop();
// Mixer 4
// sample7.loop();
synthD1.loop();
// synthD2.loop();
synthD3.loop();
// synthD4.loop();
if(msec>500){
msec=0;
Serial.print("Memory: ");
Serial.println(freeMemory());
}
}