MIDI shield- Midi file starts and plays but then stops before it´s finished .

Dear Forum
I am working on a project with arduino with the spark fun midi shield. I use a code i found in the examples MD_MIDIfile_Play and modified it only with the midi file name. . It is really complicated code for my arduino skills. I need to just play one midi file from an SD card to a midi panflute machine. (the code was for a row of files) The wohle thing seems to work . it starts and runs the file but after a while the midi file stops playing … i have no clue why it cannot play the whole file? (When opening the midi file in reaper it looks fine)
If anyone would have the knowledge and time to check it it is a code problem I would be really grateful.
Thanks! All best Camilla.
code below:

// Test playing a succession of MIDI files from the SD card.
// Example program to demonstrate the use of the MIDFile library
// Just for fun light up a LED in time to the music.
//
// Hardware required:
// SD card interface - change SD_SELECT for SPI comms
// 3 LEDs (optional) - to display current status and beat.
// Change pin definitions for specific hardware setup - defined below.

#include <SdFat.h>
#include <MD_MIDIFile.h>

#define USE_MIDI 1 // set to 1 to enable MIDI output, otherwise debug output

#if USE_MIDI // set up for direct MIDI serial output

#define DEBUG(x)
#define DEBUGX(x)
#define DEBUGS(s)
#define SERIAL_RATE 31250

#else // don’t use MIDI to allow printing debug statements

#define DEBUG(x) Serial.print(x)
#define DEBUGX(x) Serial.print(x, HEX)
#define DEBUGS(s) Serial.print(F(s))
#define SERIAL_RATE 57600

#endif // USE_MIDI

// SD chip select pin for SPI comms.
// Arduino Ethernet shield, pin 4.
// Default SD chip select is the SPI SS pin (10).
// Other hardware will be different as documented for that hardware.
const uint8_t SD_SELECT = 10;

// LED definitions for status and user indicators
const uint8_t READY_LED = 7; // when finished
const uint8_t SMF_ERROR_LED = 6; // SMF error
const uint8_t SD_ERROR_LED = 5; // SD error
const uint8_t BEAT_LED = 4; // toggles to the ‘beat’

const uint16_t WAIT_DELAY = 2000; // ms

#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 *tuneList =
{
“testpanflute.mid”, // simplest and shortest file

};

SdFat SD;
MD_MIDIFile SMF;

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 USE_MIDI
if ((pev->data[0] >= 0x80) && (pev->data[0] <= 0xe0))
{
Serial.write(pev->data[0] | pev->channel);
Serial.write(&pev->data[1], pev->size-1);
}
else
Serial.write(pev->data, pev->size);
#endif
DEBUG("\n");
DEBUG(millis());
DEBUG("\tM T");
DEBUG(pev->track);
DEBUG(": Ch “);
DEBUG(pev->channel+1);
DEBUG(” Data ");
for (uint8_t i=0; isize; i++)
{
DEBUGX(pev->data
);*

  • DEBUG(’ ');*
  • }*
    }
    void sysexCallback(sysex_event *pev)
    // Called by the MIDIFile library when a system Exclusive (sysex) file event needs
    // to be processed through the midi communications interface. Most sysex events cannot
    // really be processed, so we just ignore it here.
    // This callback is set up in the setup() function.
    {
  • DEBUG("\nS T");*
  • DEBUG(pev->track);*
  • DEBUG(": Data ");*
  • for (uint8_t i=0; isize; i++)*
  • {*
    _ DEBUGX(pev->data*);_
    _
    DEBUG(’ ');_
    _
    }_
    _
    }_
    void midiSilence(void)
    _
    // Turn everything off on every channel._
    _
    // Some midi files are badly behaved and leave notes hanging, so between songs turn*_
    // off all the notes and sound
    {
    * midi_event ev;
    _
    // All sound off*_
    * // When All Sound Off is received all oscillators will turn off, and their volume*
    * // envelopes are set to zero as soon as possible.*
    * ev.size = 0;*
    * ev.data[ev.size++] = 0xb0;*
    * ev.data[ev.size++] = 120;*
    * ev.data[ev.size++] = 0;*
    * for (ev.channel = 0; ev.channel < 16; ev.channel++)*
    * midiCallback(&ev);*
    }
    void setup(void)
    {
    * // Set up LED pins*
    * pinMode(READY_LED, OUTPUT);
    pinMode(SD_ERROR_LED, OUTPUT);
    pinMode(SMF_ERROR_LED, OUTPUT);
    pinMode(BEAT_LED, OUTPUT);
    _
    // reset LEDs*_
    * digitalWrite(READY_LED, LOW);
    digitalWrite(SD_ERROR_LED, LOW);
    digitalWrite(SMF_ERROR_LED, LOW);
    digitalWrite(BEAT_LED, LOW);*

* Serial.begin(SERIAL_RATE);
_
DEBUG("\n[MidiFile Play List]");_
_
// Initialize SD*_
* if (!SD.begin(SD_SELECT, SPI_FULL_SPEED))
_
{_
_
DEBUG("\nSD init fail!");_
digitalWrite(SD_ERROR_LED, HIGH);
_
while (true) ;_
_
}_
_
// Initialize MIDIFile*_
* SMF.begin(&SD);*
* SMF.setMidiHandler(midiCallback);*
* SMF.setSysexHandler(sysexCallback);*
* digitalWrite(READY_LED, HIGH);
_
}_
void tickMetronome(void)
_
// flash a LED to the beat*_
{
* static uint32_t lastBeatTime = 0;
_
static boolean inBeat = false;_
uint16_t beatTime;
_ beatTime = 60000/SMF.getTempo(); // msec/beat = ((60sec/min)(1000 ms/sec))/(beats/min)
* if (!inBeat)*
* {*
* if ((millis() - lastBeatTime) >= beatTime)*
* {*
* lastBeatTime = millis();*
* digitalWrite(BEAT_LED, HIGH);
_
inBeat = true;*

* }*
* }*
* else*
* {*
* if ((millis() - lastBeatTime) >= 100) // keep the flash on for 100ms only*
* {*
* digitalWrite(BEAT_LED, LOW);
_
inBeat = false;_
_
}_
_
}_
_
}_
void loop(void)
_
{_
static enum { S_IDLE, S_PLAYING, S_END, S_WAIT_BETWEEN } state = S_IDLE;
static uint16_t currTune = ARRAY_SIZE(tuneList);
static uint32_t timeStart;
_
switch (state)_
_
{_
case S_IDLE: // now idle, set up the next tune*

* {*
* int err;*
* DEBUGS("\nS_IDLE");
digitalWrite(READY_LED, LOW);
digitalWrite(SMF_ERROR_LED, LOW);
_
currTune++;_
if (currTune >= ARRAY_SIZE(tuneList))
_
currTune = 0;_
_
// use the next file name and play it*_
* DEBUG("\nFile: ");*
* DEBUG(tuneList[currTune]);*
* err = SMF.load(tuneList[currTune]);*
* if (err != MD_MIDIFile::E_OK)
_
{_
_
DEBUG(" - SMF load Error “);_
_
DEBUG(err);_
digitalWrite(SMF_ERROR_LED, HIGH);
_
timeStart = millis();_
state = S_WAIT_BETWEEN;
DEBUGS(”\nWAIT_BETWEEN");
_
}_
_
else*_
* {*
* DEBUGS("\nS_PLAYING");
state = S_PLAYING;
_
}_
_
}_
_
break;_
case S_PLAYING: // play the file*

* DEBUGS("\nS_PLAYING");
_
if (!SMF.isEOF())_
_
{_
_
if (SMF.getNextEvent())_
_
tickMetronome();_
_
}_
_
else*_
* state = S_END;
_
break;_
case S_END: // done with this one*

* DEBUGS("\nS_END");
_
SMF.close();_
_
midiSilence();_
_
timeStart = millis();_
state = S_WAIT_BETWEEN;
DEBUGS("\nWAIT_BETWEEN");
_
break;_
case S_WAIT_BETWEEN: // signal finished with a dignified pause*

* digitalWrite(READY_LED, HIGH);
if (millis() - timeStart >= WAIT_DELAY)
state = S_IDLE;
_
break;_
_
default:_
state = S_IDLE;
_
break;_
_
}_
_
}*_

Posting code the way advicd in topics like “How to use the Forum” it would hopefully look like this:

// Test playing a succession of MIDI files from the SD card.
// Example program to demonstrate the use of the MIDFile library
// Just for fun light up a LED in time to the music.
//
// Hardware required:
//  SD card interface - change SD_SELECT for SPI comms
//  3 LEDs (optional) - to display current status and beat.
//  Change pin definitions for specific hardware setup - defined below.

#include <SdFat.h>
#include <MD_MIDIFile.h>

#define USE_MIDI  1   // set to 1 to enable MIDI output, otherwise debug output

#if USE_MIDI // set up for direct MIDI serial output

#define DEBUG(x)
#define DEBUGX(x)
#define DEBUGS(s)
#define SERIAL_RATE 31250

#else // don't use MIDI to allow printing debug statements

#define DEBUG(x)  Serial.print(x)
#define DEBUGX(x) Serial.print(x, HEX)
#define DEBUGS(s) Serial.print(F(s))
#define SERIAL_RATE 57600

#endif // USE_MIDI


// SD chip select pin for SPI comms.
// Arduino Ethernet shield, pin 4.
// Default SD chip select is the SPI SS pin (10).
// Other hardware will be different as documented for that hardware.
const uint8_t SD_SELECT = 10;

// LED definitions for status and user indicators
const uint8_t READY_LED = 7;      // when finished
const uint8_t SMF_ERROR_LED = 6;  // SMF error
const uint8_t SD_ERROR_LED = 5;   // SD error
const uint8_t BEAT_LED = 4;       // toggles to the 'beat'

const uint16_t WAIT_DELAY = 2000; // ms

#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 *tuneList[] =
{
  "testpanflute.mid",  // simplest and shortest file

};


SdFat    SD;
MD_MIDIFile SMF;

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 USE_MIDI
  if ((pev->data[0] >= 0x80) && (pev->data[0] <= 0xe0))
  {
    Serial.write(pev->data[0] | pev->channel);
    Serial.write(&pev->data[1], pev->size - 1);
  }
  else
    Serial.write(pev->data, pev->size);
#endif
  DEBUG("\n");
  DEBUG(millis());
  DEBUG("\tM T");
  DEBUG(pev->track);
  DEBUG(":  Ch ");
  DEBUG(pev->channel + 1);
  DEBUG(" Data ");
  for (uint8_t i = 0; i < pev->size; i++)
  {
    DEBUGX(pev->data);
    DEBUG(' ');
  }
}

void sysexCallback(sysex_event *pev)
// Called by the MIDIFile library when a system Exclusive (sysex) file event needs
// to be processed through the midi communications interface. Most sysex events cannot
// really be processed, so we just ignore it here.
// This callback is set up in the setup() function.
{
  DEBUG("\nS T");
  DEBUG(pev->track);
  DEBUG(": Data ");
  for (uint8_t i = 0; i < pev->size; i++)
  {
    DEBUGX(pev->data);
    DEBUG(' ');
  }
}

void midiSilence(void)
// Turn everything off on every channel.
// Some midi files are badly behaved and leave notes hanging, so between songs turn
// off all the notes and sound
{
  midi_event ev;

  // All sound off
  // When All Sound Off is received all oscillators will turn off, and their volume
  // envelopes are set to zero as soon as possible.
  ev.size = 0;
  ev.data[ev.size++] = 0xb0;
  ev.data[ev.size++] = 120;
  ev.data[ev.size++] = 0;

  for (ev.channel = 0; ev.channel < 16; ev.channel++)
    midiCallback(&ev);
}

void setup(void)
{
  // Set up LED pins
  pinMode(READY_LED, OUTPUT);
  pinMode(SD_ERROR_LED, OUTPUT);
  pinMode(SMF_ERROR_LED, OUTPUT);
  pinMode(BEAT_LED, OUTPUT);

  // reset LEDs
  digitalWrite(READY_LED, LOW);
  digitalWrite(SD_ERROR_LED, LOW);
  digitalWrite(SMF_ERROR_LED, LOW);
  digitalWrite(BEAT_LED, LOW);

  Serial.begin(SERIAL_RATE);

  DEBUG("\n[MidiFile Play List]");

  // Initialize SD
  if (!SD.begin(SD_SELECT, SPI_FULL_SPEED))
  {
    DEBUG("\nSD init fail!");
    digitalWrite(SD_ERROR_LED, HIGH);
    while (true) ;
  }

  // Initialize MIDIFile
  SMF.begin(&SD);
  SMF.setMidiHandler(midiCallback);
  SMF.setSysexHandler(sysexCallback);

  digitalWrite(READY_LED, HIGH);
}

void tickMetronome(void)
// flash a LED to the beat
{
  static uint32_t lastBeatTime = 0;
  static boolean  inBeat = false;
  uint16_t  beatTime;

  beatTime = 60000 / SMF.getTempo();  // msec/beat = ((60sec/min)*(1000 ms/sec))/(beats/min)
  if (!inBeat)
  {
    if ((millis() - lastBeatTime) >= beatTime)
    {
      lastBeatTime = millis();
      digitalWrite(BEAT_LED, HIGH);
      inBeat = true;
    }
  }
  else
  {
    if ((millis() - lastBeatTime) >= 100)    // keep the flash on for 100ms only
    {
      digitalWrite(BEAT_LED, LOW);
      inBeat = false;
    }
  }
}

void loop(void)
{
  static enum { S_IDLE, S_PLAYING, S_END, S_WAIT_BETWEEN } 
  state = S_IDLE;
  static uint16_t currTune = ARRAY_SIZE(tuneList);
  static uint32_t timeStart;

  switch (state)
  {
    case S_IDLE:    // now idle, set up the next tune
      {
        int err;

        DEBUGS("\nS_IDLE");

        digitalWrite(READY_LED, LOW);
        digitalWrite(SMF_ERROR_LED, LOW);

        currTune++;
        if (currTune >= ARRAY_SIZE(tuneList))
          currTune = 0;

        // use the next file name and play it
        DEBUG("\nFile: ");
        DEBUG(tuneList[currTune]);
        err = SMF.load(tuneList[currTune]);
        if (err != MD_MIDIFile::E_OK)
        {
          DEBUG(" - SMF load Error ");
          DEBUG(err);
          digitalWrite(SMF_ERROR_LED, HIGH);
          timeStart = millis();
          state = S_WAIT_BETWEEN;
          DEBUGS("\nWAIT_BETWEEN");
        }
        else
        {
          DEBUGS("\nS_PLAYING");
          state = S_PLAYING;
        }
      }
      break;

    case S_PLAYING: // play the file
      DEBUGS("\nS_PLAYING");
      if (!SMF.isEOF())
      {
        if (SMF.getNextEvent())
          tickMetronome();
      }
      else
        state = S_END;
      break;

    case S_END:   // done with this one
      DEBUGS("\nS_END");
      SMF.close();
      midiSilence();
      timeStart = millis();
      state = S_WAIT_BETWEEN;
      DEBUGS("\nWAIT_BETWEEN");
      break;

    case S_WAIT_BETWEEN:    // signal finished with a dignified pause
      digitalWrite(READY_LED, HIGH);
      if (millis() - timeStart >= WAIT_DELAY)
        state = S_IDLE;
      break;

    default:
      state = S_IDLE;
      break;
  }
}

Have You verified that the SD files are in order? Are they all there?

I only have one file to play. i couldn´t find an exaple with playing only one midi file

Is there any way You can test that file, using other equipment, and verify the integrity, the length, of the file?

yes i tested it in reaper. Is there any example code that only plays one midi file of an sd card?

How long time does it run before the stop?
I suspect a power problem and ask You to post a wiring diagram, not any Fritzing wall decorations. I want to see the power sources involved.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.