Library for playing MIDI files from the Arduino

Thanks for your work on this -- I can see a lot of applications and think it will be helpful for a lot of people.

I have a related newbie question: For those of us without an SD-enabled Ethernet shield, what adjustments should be made? I have an adafruit waveshield and will be getting an SD breakout shield, but I'm not sure what modifications in SD reading pins to make. For instance, your MIDIFile_Play sample uses "#define SD_SELECT 4"; it might be helpful to explain what an "SD chip select pin" is and what other common values might be for other arduino versions or shields with SD readers.

Also, I imagine it would be possible to store very small MIDI files in the arduino's memory itself. That would open up some options for people who want to play back simple music or other actions (lights, servos, etc.) with an open, easy-to-modify standard like MIDI, but without needing to include an SD card in their setup. Would that be hard to do? What would be the best way to approach that?

Thanks again. Looking forward to learning enough to use this.

What would be the best way to approach that?

Start building it.

Quote

Yes, there will be a pint release once I can check a few things.
I like that

Sometimes typos probably reflect the truth ...

Pint release is on the download site.

For those of us without an SD-enabled Ethernet shield, what adjustments should be made?

Depends on your hardware.

it might be helpful to explain what an "SD chip select pin" is and what other common values might be for other arduino versions or shields with SD readers

SD cards use the SPI pins on the Arduino to transfer data. This is a bus (ie, multiple devices can be connected to the same pins to send and receive data), so a device needs to know when it needs to communicate. This is done by a SELECT line, and each SPI devices needs a separate select line. The SD_SELECT define is the pin to use to select the SD card in the SdFat library.

What you need to change it to depends on how your hardware is configured, and will be documented as part of you hardware. Common values are Arduino Ethernet shield pin 4, Sparkfun SD shield pin 8, Adafruit SD shields and modules pin 10. The main thing is that all of these devices need to coexist and not use the same pin or we can't select the device independently of the others. This pin also can't be used for anything else in the program.

Also, I imagine it would be possible to store very small MIDI files in the arduino's memory itself

They would be very small indeed, as the files would need to be stored in RAM for them to be edited, which on my Uno is very small. This is not the same as the program storage memory, by the way, which is reported by the IDE when you compile your programs.

Would that be hard to do? What would be the best way to approach that?

Not especially. However, if you have a program that always plays the same music, then the music is hard coded in the software that you write. At that point you are not interpreting a MIDI file, but just sending out MIDI commands through the serial port - you don't need the overhead of a library like this one.

SD card readers are not that expensive. I got one recently from eBay for less than $1.50 (http://www.ebay.com.au/itm/280780639068?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649) that could be used as-is in a breadboard setup. I chose to mount it permanently onto a prototyping shield and put in a jumper so that I could change the select line anywhere between pins 2 and 10 so that I am less likely to clash with other cards. All up probably cost $5.

New version 1.2 of the library has been loaded to my repository (see signature).

v1.2 has examples cleaned up and better commented. The dependency on the MIDI library has been removed . There are no dignificant changes to the core library.

I am running arduino 1.0.5, I have the appropriate libraries Midi, Data flash, midifile, Sdfat... I plan on running MIDIFile_Play_LCD on a uno SDsheild and 2x16 LCD. So far just setting up libraries and waiting on a mouser order. I am a bit new to micros but not to electronics, and this is my 2nd arduino project...

Problem is when i compile the sketch i get this error
'A0' was not declared in this scope

In file included from MIDIFile_Play_LCD.ino:14:
KeyPress.h: In function 'char getLCDKey()':
KeyPress.h:32: error: 'A0' was not declared in this scope
KeyPress.h:32: error: 'analogRead' was not declared in this scope
KeyPress.h:35: error: 'millis' was not declared in this scope
MIDIFile_Play_LCD.ino: At global scope:
MIDIFile_Play_LCD:47: error: variable or field 'midiCallback' declared void
MIDIFile_Play_LCD:47: error: 'midi_event' was not declared in this scope
MIDIFile_Play_LCD:47: error: 'pev' was not declared in this scope
MIDIFile_Play_LCD:48: error: variable or field 'sysexCallback' declared void
MIDIFile_Play_LCD:48: error: 'sysex_event' was not declared in this scope
MIDIFile_Play_LCD:48: error: 'pev' was not declared in this scope
MIDIFile_Play_LCD:69: error: 'SdFat' does not name a type
MIDIFile_Play_LCD:70: error: 'MIDIFile' does not name a type
MIDIFile_Play_LCD:79: error: variable or field 'midiCallback' declared void
MIDIFile_Play_LCD:79: error: 'midi_event' was not declared in this scope
MIDIFile_Play_LCD:79: error: 'pev' was not declared in this scope

i am guessing it has something to do with my libraries? Any help would be appreciated :slight_smile:

A 'oh' or A 'zero'? Are you compiling a standard example?

I have just tried it on my system and it works ok with 1.0.5.

thank you for the fast reply
that was 'A ZERO'

now i reloaded libraries and I get a long string of errors when I verify the sketch in the main MIDIFile_Play_LCD tab it reads

'SdFat' does not name a type

In file included from MIDIFile_Play_LCD.ino:11:
/Users/scriptstyle/Documents/Arduino/libraries/MIDIFile/MIDIFile.h:174: error: 'SdFat' has not been declared
/Users/scriptstyle/Documents/Arduino/libraries/MIDIFile/MIDIFile.h:259: error: ISO C++ forbids declaration of 'SdFat' with no type
/Users/scriptstyle/Documents/Arduino/libraries/MIDIFile/MIDIFile.h:259: error: expected ';' before '*' token
/Users/scriptstyle/Documents/Arduino/libraries/MIDIFile/MIDIFile.h:260: error: 'SdFile' does not name a type
MIDIFile_Play_LCD:69: error: 'SdFat' does not name a type
MIDIFile_Play_LCD.ino: In function 'uint16_t createPlaylistFile()':
MIDIFile_Play_LCD:166: error: 'SdFile' was not declared in this scope
MIDIFile_Play_LCD:166: error: expected ;' before 'plFile' MIDIFile_Play_LCD:167: error: expected ;' before 'mFile'
MIDIFile_Play_LCD:172: error: 'plFile' was not declared in this scope
MIDIFile_Play_LCD:172: error: 'O_CREAT' was not declared in this scope
MIDIFile_Play_LCD:172: error: 'O_WRITE' was not declared in this scope
MIDIFile_Play_LCD:176: error: 'mFile' was not declared in this scope
MIDIFile_Play_LCD:176: error: 'SD' was not declared in this scope
MIDIFile_Play_LCD:176: error: 'O_READ' was not declared in this scope
MIDIFile_Play_LCD:184: error: 'plFile' was not declared in this scope
MIDIFile_Play_LCD:192: error: 'plFile' was not declared in this scope
MIDIFile_Play_LCD.ino: In function 'seq_state lcdFSM(seq_state)':
MIDIFile_Play_LCD:205: error: 'SdFile' does not name a type
MIDIFile_Play_LCD:212: error: 'plFile' was not declared in this scope
MIDIFile_Play_LCD:214: error: 'O_READ' was not declared in this scope
MIDIFile_Play_LCD:221: error: 'plFile' was not declared in this scope
MIDIFile_Play_LCD.ino: In function 'void setup()':
MIDIFile_Play_LCD:371: error: 'SD' was not declared in this scope
MIDIFile_Play_LCD:376: error: 'SPI_FULL_SPEED' was not declared in this scope

i am just trying to compile/verify your original sketch so i can upload to the uno and move on from there...

with the file MIDIFile.h in my library I get the SDfat does not name a type errors, but when i delete MIDIFile.h from the library it skips that error goes to the keypress tab and reads, 'AO' was not declared in scope. and that does read as A-oh sorry. What am i missing with these errors?

I am not sure what is happening here. You may be better posting this in the general programming section of the forum as I don't think this is related to the library but more likely to the way your system is organised.

ok so i made some progress i now have the sketch loading to my uno just fine.

I am using a SD shield from seeed studio. I am almost 100% sure this is working properly, I ran SD example cardinfo: wiring is correct & card is present, and then it goes on show midi files on the card in the serial monitor.

I am using a 2x16 LCD i followed this correction and seemed to get it displaying characters but dosnt, seem to give a menu

// LCD pin definitions ---------
// These need to be modified for the LCD hardware setup
#define  LCD_RS    8
#define  LCD_ENA   9
#define  LCD_D4    4
#define  LCD_D5    (LCD_D4+1)
#define  LCD_D6    (LCD_D4+2)
#define  LCD_D7    (LCD_D4+3)

D5-1
D6-2
D7-3
LCD reads like this, i dont think this is the menu readout???

Also i used this schematic to wire up a keypad, are these values same as what is expected? input on A0

#define  LCD_D4    4
#define  LCD_D5    (LCD_D4+1)
#define  LCD_D6    (LCD_D4+2)
#define  LCD_D7    (LCD_D4+3)

D5 = D4 + 1 ==> 5. Similarly for the other 6, 7.

You need to check the code for the values that are used to separate the buttons and substitute your values for those in the code.

Looks like you are close!

// LCD pin definitions ---------
// These need to be modified for the LCD hardware setup
#define  LCD_RS    12
#define  LCD_ENA   11
#define  LCD_D4    5
#define  LCD_D5    4
#define  LCD_D6    3
#define  LCD_D7    2

so i have the LCD working. it reads Midi Player on bootup, but then nothing happens.

this is fun i am learning i learned how to use the analogreadserial function on A0 for my momentary switches

const TKEYDEF keyDefTable[] = 
{
  {   0, 10, 'R' },	// Right
  { 150, 15, 'U' },	// Up
  { 349, 15, 'D' },	// Down
  { 516, 15, 'L' },	// Left
  { 758, 15, 'S' }	// Select
};

i now have these values in the left column added, did i add these correctly? Also I am almost positive i shouldn't need to change anything in the sketch for the seeed SD shield...??? When i ran SD cardinfo all seemed well.... I know i am really close now that i can read Midi Player

Also I am almost positive i shouldn't need to change anything in the sketch for the seeed SD shield...???

As for the other parts, you need to check that the interface pins in the software setup match the hardware. Try running one of the examples from the SD/SDFat library (whichever you are using) to make sure the SD card interface works.

i now have these values in the left column added, did i add these correctly?

Looks like it - does it work?

it reads Midi Player on bootup, but then nothing happens.

Do you mean it displays "MIDI Player"? If nothing else is happening then probably your SD card pins setup is not right. See above.

Try running one of the examples from the SD/SDFat library (whichever you are using) to make sure the SD card interface works.

Ok so i tried a few incarnations of this adding and subtracting libraries and it seems like i am able to read the SD just fine pin select 10 is working fine in every example.

Do you mean it displays "MIDI Player"? If nothing else is happening then probably your SD card pins setup is not right. See above.

I am able to get "Midi Player" but then it just gets stuck. I t also seems that there is a blank text document showing up on the SD card after each attempt...

Are there any music files on the SD card? You should use the MIDI examples that are with the library and copy them to the SD card.

no music files i have only been trying midi type zero files in all different orders of; in a folder or separate now i have just been testing with your files assuming they are all type0. I have tried in all arrangements of the library of the SdFat. Not sure what the best next step should be...?

Really appreciate this library and your help so far i am very excited to build with this! :smiley:

haha silly of me to think i could use enable on the LCD and RS over the SPI ports. Thanks again for all the help. I have a large amount of midi files i am going to be trying with is there anything to look out for that you would like me to report back on?

Hello guys, as I am REALLY new arduino (like 2 days) and without any experience in C++ but some in C,
I've been trying to understand the library with a bit of difficulty.
I gave myself an easy task: create a little drum sequencer of 12 buttons.
I would like to stock the midi files, read from the SD card in an array, but I don't know how to get the data, you'll see the missing line... I don't understand well the role of "getNextEvent" function and if this is what I need to use.

Do you see anything else I should know before I get embroiled ?
Thank you !

void  setup(void)
{
  int      err;
  int      track = 0;
  byte     array[12][128];
	for (uint8_t i=0; i<ARRAY_SIZE(array); i++) //gets size of array to ignore the rest of tunelist, if > 12;
	{
	  SMF.setFilename(tuneList[i]);
	  err = SMF.load();
	  if (err == -2) // File doesn't exist or isn't properly formatted;
	          ;// fill array[data] with notes Off;
	  else
	  {
                byte  data = 0;
		smf.setTempo(100);
                while (!SMF.isEOF() || data < 128)
                    array[track][data++] = // ?
                while (data < 128)
                   array[track][data++] = 0x80; // only if the MIDI file is too short, fills with NoteOff;
                track++;
		SMF.close();
		midiSilence();
		delay(WAIT_DELAY);
	  }
	}
}