Playing notes on an electric piano in a constant interval

Hi everyone,

I tried googling my problem beforehand but I am not really sure what to call it.

My situation is basically this:

  • I have a timer (millis) running so I can have several functions going at the same time.
  • I want to have a signal to be sent out every x milliseconds.

To be more specific: It is about playing notes an an electric piano.
I would like to have a signal for 500 ms and after that a rest for 500 ms. So no signal is being sent at that rest. This should repeat several times.

I could have a funtion with 32 if-statements (8 notes per measure, 4 measures). But I am sure there is a smarter way to approach this.

Thanks in advance,
Leon

What's your C skill?

You can implement a linked list of pressed keys, together with their release time. Then you only have to look at the list head, when which signal has to be reset.

The specification is not exactly clear but it sounds like you would do well to have a look at what arrays and for loops can do.

Steve

DrDiettrich:
What's your C skill?

You can implement a linked list of pressed keys, together with their release time. Then you only have to look at the list head, when which signal has to be reset.

I am not experienced at C. I do not know if this is an advanced operation. Can you maybe give me some keywords so I can google it myself?

slipstick:
The specification is not exactly clear but it sounds like you would do well to have a look at what arrays and for loops can do.
array - Arduino Reference
for - Arduino Reference

Steve

Thanks! I will have a look at it.

//Variablenbestimmung========================================================================================================


// Zeitbezogene Variablen
int beat = 0;
unsigned long timer = 0;
long currentMillis = 0; //die Variable speichert die verstrichene Zeit in ms

//weitere Variablen
int notenHoehenPoti = 0;
int tempoPoti = 0;
int tempoDiv = 0;
int style = 0; //die Variable, die angibt, ob z.b. Funk, Pop, etc. als Jam-Track läuft


//Note 1
int note1Hoehe = 0;
unsigned long previousNote1Millis = 0;
int note1Raster = 0;
int note1Dauer = 0;

//Note 2
int note2Hoehe = 0;
unsigned long previousNote2Millis = 0;
int note2Raster = 0;
int note2Dauer = 0;

//Note 3
int note3Hoehe = 0;
unsigned long previousNote3Millis = 0;
int note3Raster = 0;
int note3Dauer = 0;

//Note 4
int note4Hoehe = 0;
unsigned long previousNote4Millis = 0;
int note4Raster = 0;
int note4Dauer = 0;


//Notendauer
const int ganze    = beat*4;
const int halbep   = beat*3; //Halbe punktierte Note
const int halbe    = beat*2;
const int viertelp = beat + beat/2;
const int viertel  = beat;
const int achtel   = beat/2;

//Notenpositionen im Takt
const int achtel0 = 0;
const int achtel1 = beat/2;
const int achtel2 = beat;
const int achtel3 = beat + beat/2;
const int achtel4 = beat*2;
const int achtel5 = beat*2 + beat/2;
const int achtel6 = beat*3;
const int achtel7 = beat*3 + beat/2;


//Matrix

//rows
const byte a = B11111111; //row 0
const byte b = B01111111; //row 1
const byte c = B10111111; //etc.
const byte d = B11011111;
const byte e = B11101111;
const byte f = B11110111;
const byte g = B11111011;
const byte h = B11111101;
const byte i = B11111110;

//columns
const byte A = B11111111; //column 0, bzw. defcolumn
const byte B = B01111111; //column 1
const byte C = B10111111; //etc.
const byte D = B11011111;
const byte E = B11101111;
const byte F = B11110111;
const byte G = B11111011;
const byte H = B11111101;
const byte I = B11111110;

const byte defcolumn = B11111111;


//Tonspezifische Zuordnungen

//Zuordnung von Zahlenwerten für Töne
const  int Czwei   = 0; //existiert nicht
const int Ciszwei  = 1; //existiert nicht
const int Dzwei    = 2; //existiert nicht
const int Diszwei  = 3; //existiert nicht
const int Ezwei    = 4; //existiert nicht
const int Fzwei    = 5;
const int Fiszwei  = 6;
const int Gzwei    = 7;
const int Giszwei  = 8;
const int Azwei    = 9;
const int Aiszwei  = 10;
const int Hzwei    = 11;
const int Cdrei    = 12;
const int Cisdrei  = 13;
const int Ddrei    = 14;
const int Disdrei  = 15;
const int Edrei    = 16;
const int Fdrei    = 17;
const int Fisdrei  = 18;
const int Gdrei    = 19;
const int Gisdrei  = 20;
const int Adrei    = 21;
const int Aisdrei  = 22;
const int Hdrei    = 23;
const int Cvier    = 24;
const int Cisvier  = 25;
const int Dvier    = 26;
const int Disvier  = 27;
const int Evier    = 28;
const int Fvier    = 29;
const int Fisvier  = 30;
const int Gvier    = 31;
const int Gisvier  = 32;
const int Avier    = 33;
const int Aisvier  = 34;
const int Hvier    = 35;
const int Cfuenf   = 36;
const int Cisfuenf = 37;
const int Dfuenf   = 38;
const int Disfuenf = 39;
const int Efuenf   = 40;
const int Ffuenf   = 41;
const int Fisfuenf = 42;
const int Gfuenf   = 43;
const int Gisfuenf = 44;
const int Afuenf   = 45;
const int Aisfuenf = 46;
const int Hfuenf   = 47;
const int Kick     = 48;
const int Snare    = 49;
const int HiHat    = 50;
const int Baya     = 51;
const int Tabla    = 52;


//rows pro Ton
int row[53]    = {a,a,a,a,a,c,c,c,c,c,c,c,c,b,b,b,b,b,b,b,b,e,e,e,e,e,e,e,e,d,d,d,d,d,d,d,a,f,f,f,f,g,g,g,g,f,f,f,h,h,h,h,h};

//columns pro Ton
int column[53] = {A,A,A,A,A,H,I,F,G,D,E,B,C,H,I,F,G,D,E,B,C,H,I,F,G,D,E,B,C,H,I,F,G,D,E,B,A,D,E,B,C,D,E,B,C,H,I,F,G,F,D,E,B};



//Halbtonschritte der Intervalle
const int klSek    = 1;
const int grSek    = 2;
const int klTerz   = 3;
const int grTerz   = 4;
const int Quart    = 5;
const int uebQuart = 6;
const int Quint    = 7;
const int klSext   = 8;
const int grSext   = 9;
const int klSept   = 10;
const int grSept   = 11;
const int Okt      = 12;



//Setup======================================================================================================================



void setup() {

//Ein- und Ausgänge definieren
  DDRC = B00000000;       // 1 = Output, 0 = Input
  DDRA = B11111111;       

}



//Loop=======================================================================================================================



void loop() {

//tempoPoti mappen
map(tempoPoti, 0, 255, 1, 3); //reale Werte auslesen und dementsprechend "fromLow" und "fromHigh" anpassen, BPM zwischen 60 und 180 

//tempoDiv definieren
tempoDiv = tempoPoti;

//Stoppuhr  
timer = millis()*tempoDiv; //Stoppuhr in ms
currentMillis += timer

//Beat an currentMillis angleichen
beat = 1000;


//notenHoehenPoti mappen
map(notenHoehenPoti, 0, 255, 0, 11); //0 bis 11 sind die Haltonschritte zwischen Grundton und dem letzten Ton vor der Oktave, hier auch mit realen Werten angleichen


//Noten
note1Hoehe = Cdrei + notenHoehenPoti;
note2Hoehe = note1Hoehe + grTerz;
note3Hoehe = note1Hoehe + klTerz;


//Notenfunktionen
note1(note1Hoehe, achtel0, ganze);
note2(note2Hoehe, achtel0, ganze);
note3(note3Hoehe, achtel0, ganze);
}



//Funktionen=================================================================================================================



//zeitliche Abstimmung der Singalausgabe 
void play (byte row1, byte column1) {

if (PINC == row1) {
  PORTA = column1;
  
} else {
  PORTA = defcolumn; 
}
  
}



//TimerReset=================================================================================================================



void timerReset (){
  if (currentMillis = beat*16*1000){ //vier Takte haben 16 Schläge (4*4) 
    currentMillis -= timer*2
  }
}



//Funktionen pro Ton=========================================================================================================



//Note 1
void note1 (){

if ((currentMillis >= 0) && (currentMillis < ganze-50)){ //-50 wegen Abtastrate
  play (row[Gdrei], column[Gdrei]);  
  }

if ((currentMillis >= ganze) && (currentMillis < (ganze*2)-50)){
  play (row[Adrei], column[Adrei]);  

if ((currentMillis >= (ganze*2)) && (currentMillis < (ganze*3)-50)){
  play (row[Gdrei], column[Gdrei]);  
  }

if ((currentMillis >= (ganze*3)) && (currentMillis < (ganze*4)-50)){
  play (row[Adrei], column[Adrei]);  
  }  
}  



//Note 2
void note2 (int note2Hoehe, int notenraster2, int notendauer2){

if ((currentMillis >= 0) && (currentMillis < ganze-50)){ 
  play (row[Hdrei], column[Hdrei]);  
  }

if ((currentMillis >= ganze) && (currentMillis < (ganze*2)-50)){
  play (row[Cvier], column[Cvier]);  

if ((currentMillis >= (ganze*2)) && (currentMillis < (ganze*3)-50)){
  play (row[Hdrei], column[Hdrei]);  
  }

if ((currentMillis >= (ganze*3)) && (currentMillis < (ganze*4)-50)){
  play (row[Cvier], column[Cvier]);  
  }  
}  



//Note 3
void note3 (int note3Hoehe, int notenraster3, int notendauer3){

if ((currentMillis >= 0) && (currentMillis < ganze-50)){
  play (row[Evier], column[Evier]);  
  }

if ((currentMillis >= ganze) && (currentMillis < (ganze*2)-50)){
  play (row[Evier], column[Evier]);  

if ((currentMillis >= (ganze*2)) && (currentMillis < (ganze*3)-50)){
  play (row[Evier], column[Evier]);  
  }

if ((currentMillis >= (ganze*3)) && (currentMillis < (ganze*4)-50)){
  play (row[Evier], column[Evier]);  
  }  
}  



//Kick



//Snare



//HiHat



//MIDI-Ausgabe===============================================================================================================



//MIDI-Ausgabe
//void midi1 (int style){

slipstick:
The specification is not exactly clear but it sounds like you would do well to have a look at what arrays and for loops can do.
array - Arduino Reference
for - Arduino Reference

Steve

I posted my code above. I hope this makes things a little clearer. I hope you do get the point even though there are many German words in there.
The section which my question is about is the one called "//Funktionen pro Ton===". You can find it in the lower half of the code.