Had time to run this today, nice job.
The code also runs on a VEX EXP brain with almost no modification, just change the controller button events. EXP has a bit more sound capability than IQ2, it has sharps/flats available as notes and 4 octaves. It can also play wav files from the SD card (mono and less than 22.5k sample rate).
here is some demo code showing how to play the tetris theme in both ways (assumes a file Tetris.wav is on SD card).
demo code
/*----------------------------------------------------------------------------*/
/* */
/* Module: main.cpp */
/* Author: james */
/* Created: 3/3/2024, 3:08:15 PM */
/* Description: EXP project */
/* */
/* Based on code by Robson Couto modified for EXP. */
/* */
/* Tetris theme - (Korobeiniki) */
/* More songs available at https://github.com/robsoncouto/arduino-songs */
/* */
/* Robson Couto, 2019 */
/* */
/*----------------------------------------------------------------------------*/
#include "vex.h"
using namespace vex;
// A global instance of vex::brain used for printing to the EXP brain screen
vex::brain Brain;
#define NOTE_C4 0
#define NOTE_CS4 1
#define NOTE_D4 2
#define NOTE_DS4 3
#define NOTE_E4 4
#define NOTE_F4 5
#define NOTE_FS4 6
#define NOTE_G4 7
#define NOTE_GS4 8
#define NOTE_A4 9
#define NOTE_AS4 10
#define NOTE_B4 11
#define NOTE_C5 12
#define NOTE_CS5 13
#define NOTE_D5 14
#define NOTE_DS5 15
#define NOTE_E5 16
#define NOTE_F5 17
#define NOTE_FS5 18
#define NOTE_G5 19
#define NOTE_GS5 20
#define NOTE_A5 21
#define NOTE_AS5 22
#define NOTE_B5 23
#define NOTE_C6 24
#define NOTE_CS6 25
#define NOTE_D6 26
#define NOTE_DS6 27
#define NOTE_E6 28
#define NOTE_F6 29
#define NOTE_FS6 30
#define NOTE_G6 31
#define NOTE_GS6 32
#define NOTE_A6 33
#define NOTE_AS6 34
#define NOTE_B6 35
#define REST 99
// change this to make the song slower or faster
int tempo=144;
// notes of the moledy followed by the duration.
// a 4 means a quarter note, 8 an eighteenth , 16 sixteenth, so on
// !!negative numbers are used to represent dotted notes,
// so -4 means a dotted quarter note, that is, a quarter plus an eighteenth!!
int melody[] = {
//Based on the arrangement at https://www.flutetunes.com/tunes.php?id=192
NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8,
NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8,
NOTE_B4, -4, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4,
NOTE_C5, 4, NOTE_A4,4, NOTE_A4,8, NOTE_A4,4, NOTE_B4,8, NOTE_C5,8,
NOTE_D5, -4, NOTE_F5,8, NOTE_A5,4, NOTE_G5,8, NOTE_F5,8,
NOTE_E5, -4, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8,
NOTE_B4, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4,
NOTE_C5, 4, NOTE_A4,4, NOTE_A4,4, REST, 4,
NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8,
NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8,
NOTE_B4, -4, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4,
NOTE_C5, 4, NOTE_A4,4, NOTE_A4,8, NOTE_A4,4, NOTE_B4,8, NOTE_C5,8,
NOTE_D5, -4, NOTE_F5,8, NOTE_A5,4, NOTE_G5,8, NOTE_F5,8,
NOTE_E5, -4, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8,
NOTE_B4, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4,
NOTE_C5, 4, NOTE_A4,4, NOTE_A4,4, REST, 4,
NOTE_E5,2, NOTE_C5,2,
NOTE_D5,2, NOTE_B4,2,
NOTE_C5,2, NOTE_A4,2,
NOTE_GS4,2, NOTE_B4,4, REST,8,
NOTE_E5,2, NOTE_C5,2,
NOTE_D5,2, NOTE_B4,2,
NOTE_C5,4, NOTE_E5,4, NOTE_A5,2,
NOTE_GS5,2,
};
void soundTrack() {
// sizeof gives the number of bytes, each int value is composed of two bytes (16 bits)
// there are two values per note (pitch and duration), so for each note there are four bytes
int notes=sizeof(melody)/sizeof(melody[0])/2;
// this calculates the duration of a whole note in ms (60s/tempo)*4 beats
int wholenote = (60000 * 4) / tempo;
int volume = 10;
int divider = 0, noteDuration = 0;
while(1) {
// iterate over the notes of the melody.
// Remember, the array is twice the number of notes (notes + durations)
for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
// calculates the duration of each note
divider = melody[thisNote + 1];
if (divider > 0) {
// regular note, just proceed
noteDuration = (wholenote) / divider;
} else if (divider < 0) {
// dotted notes are represented with negative durations!!
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
if( melody[thisNote] == 99 ) {
// rest
this_thread::sleep_for(noteDuration);
}
else {
// we only play the note for 90% of the duration, leaving 10% as a pause
Brain.playNote( melody[thisNote] / 12, melody[thisNote] % 12, noteDuration*0.9, volume );
this_thread::sleep_for(noteDuration*0.1);
}
}
}
}
int
soundTrackUsingWav() {
int volume = 10;
while(1) {
Brain.playFile("Tetris.wav", volume);
// wait for completion
while(Brain.soundIsActive() ) {
this_thread::sleep_for(100);
}
}
return 0;
}
int main() {
//thread t1(soundTrackUsingWav);
soundTrack();
while(1)
this_thread::sleep_for(500);
}