Lab_interaccio/2021/Paonessa_SD_MIDI/Paonessa_SD_MIDI.ino

187 lines
4.7 KiB
Arduino
Raw Normal View History

2025-02-25 21:29:42 +01:00
// Play a file from the SD card in looping mode, from the SD card.
// Example program to demonstrate the use of the MIDFile library
//
// Hardware required:
// SD card interface - change SD_SELECT for SPI comms
#include <SdFat.h>
#include <MD_MIDIFile.h>
#define DEBUG_ON true // set to 1 for MIDI output, 0 for debug output
#define GENERATE_TICKS 1
#define DEBUGS(s) uart.print(s)
#define DEBUG(s, x) { uart.print(F(s)); uart.print(x); }
#define DEBUGX(s, x) { uart.print(F(s)); uart.print(x, HEX); }
#define uart_RATE 115200
#if defined(ARDUINO_ARCH_SAMD)
#define SD_SELECT 4
int pin_out[6] = {13, 11, 10, 9, 6, 5};
#else
#define SD_SELECT 4
int pin_out[6] = {13, 27, 33, 15, 32, 14};
#endif
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
// The files in the tune list should be located on the SD card
// or an error will occur opening the file and the next in the
// list will be opened (skips errors).
const char *loopfile = "Music1.mid"; // simple and short file
#if GENERATE_TICKS
//uint32_t lclBPM = 135;
#define _lclBPM 90
uint32_t lclBPM = _lclBPM;
#endif
SdFat SD;
MD_MIDIFile SMF;
#if defined(ARDUINO_ARCH_SAMD)
#define uart SerialUSB
#endif
byte state_ = 0;
byte channel_ = 0;
byte intensity_ = 0;
void midiCallback(midi_event *pev)
// Called by the MIDIFile library when a file event needs to be processed
// thru the midi communications interface.
// This callback is set up in the setup() function.
{
#if DEBUG_ON
DEBUG("M T", pev->track);
DEBUG(": Ch ", pev->channel+1);
DEBUGS(" Data");
#endif
state_ = pev->data[0];
channel_ = pev->data[1];
intensity_ = pev->data[2];
#if DEBUG_ON
DEBUGX(" ", state_);
DEBUGX(" ", channel_);
DEBUGX(" ", intensity_);
uart.print(" ");
uart.print((channel_), HEX);
uart.print(" ");
uart.print(pin_out[channel_-0x24]);
#endif
if (intensity_>0)
{
digitalWrite(pin_out[channel_-0x24], HIGH);
#if DEBUG_ON
uart.println(" Solenoide ON");
#endif
}
else
if (intensity_==0)
{
digitalWrite(pin_out[channel_-0x24], LOW);
#if DEBUG_ON
uart.println(" Solenoide OFF");
#endif
}
}
#if GENERATE_TICKS
uint16_t tickClock(void)
// Check if enough time has passed for a MIDI tick and work out how many!
{
static uint32_t lastTickCheckTime, lastTickError;
uint8_t ticks = 0;
uint32_t elapsedTime = lastTickError + micros() - lastTickCheckTime;
uint32_t tickTime = (60 * 1000000L) / (lclBPM * SMF.getTicksPerQuarterNote()); // microseconds per tick
tickTime = (tickTime * 4) / (SMF.getTimeSignature() & 0xf); // Adjusted for time signature
if (elapsedTime >= tickTime)
{
ticks = elapsedTime/tickTime;
lastTickError = elapsedTime - (tickTime * ticks);
lastTickCheckTime = micros(); // save for next round of checks
}
return(ticks);
}
#endif
void setup(void)
{
int err;
#if DEBUG_ON
uart.begin(uart_RATE);
#endif
delay(4000);
#if defined(ARDUINO_ARCH_SAMD)
analogReadResolution(12);
#endif
for(int i=0; i<6; i++)
{
pinMode(pin_out[i], OUTPUT);
digitalWrite(pin_out[i], LOW);
}
DEBUGS("\n[MidiFile Looper]");
// Initialize SD
if (!SD.begin(SD_SELECT, SPI_HALF_SPEED))
{
DEBUGS("\nSD init fail!");
while (true) ;
}
// Initialize MIDIFile
SMF.begin(&SD);
SMF.setMidiHandler(midiCallback);
SMF.looping(false);
// use the next file name and play it
DEBUG("\nFile: ", loopfile);
SMF.setFilename(loopfile);
err = SMF.load(loopfile);
if (err != MD_MIDIFile::E_OK)
{
DEBUG("\nSMF load Error ", err);
while (true);
}
}
void loop(void)
{
//uart.println(analogRead(A0));
#if GENERATE_TICKS
static bool fBeat = false;
static uint16_t sumTicks = 0;
uint32_t ticks = tickClock();
lclBPM = map(analogRead(A0), 0, 4095, -(_lclBPM - 30), (_lclBPM - 30)) + _lclBPM;
#if DEBUG_ON
//uart.println(lclBPM);
#endif
if (ticks > 0)
{
SMF.processEvents(ticks);
// SMF.isEOF(); // side effect to cause restart at EOF if looping
// sumTicks += ticks;
// if (sumTicks >= SMF.getTicksPerQuarterNote())
// {
// sumTicks = 0;
// fBeat = !fBeat;
// }
if(!SMF.isEOF()){ // side effect to cause restart at EOF if looping
sumTicks += ticks;
if (sumTicks >= SMF.getTicksPerQuarterNote())
{
sumTicks = 0;
fBeat = !fBeat;
}}
}
#else
// play the file
if (!SMF.isEOF())
{
SMF.getNextEvent();
}
#endif*/
}