Pages: 1 [2] 3 4   Go Down
Author Topic: MIDI library conflict?  (Read 4353 times)
0 Members and 1 Guest are viewing this topic.
Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1285
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just cast the data[0] parameter to midi::MidiType.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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);

  MIDI.send((midi::MidiType)pev->data[0], (pev->data[1]), (pev->data[2]), (pev->channel));
 

}
else
Serial.write(pev->data, pev->size);
#endif

  DEBUG("\nM T");
  DEBUG(pev->track);
  DEBUG(":  Ch ");
  DEBUG(pev->channel+1);
  DEBUG(" Data ");
  for (uint8_t i=0; i<pev->size; i++)
  {
DEBUGX((midi::MidiType)pev->data[i]);
    DEBUG(' ');
  }
}


I tried this and I get nothing.  When I debug, i see it looks fine to me:

M T0:  Ch 1 Data 90 48 64
M T0:  Ch 1 Data 80 48 40
M T0:  Ch 1 Data 90 49 64
M T0:  Ch 1 Data 80 49 40
M T0:  Ch 1 Data 90 4A 64
M T0:  Ch 1 Data 80 4A 40
M T0:  Ch 1 Data 90 4B 64
M T0:  Ch 1 Data 80 4B 40
M T0:  Ch 1 Data 90 4C 64
M T0:  Ch 1 Data 80 4C 40
M T0:  Ch 1 Data 90 4D 64
M T0:  Ch 1 Data 80 4D 40
M T0:  Ch 1 Data 90 4E 64
M T0:  Ch 1 Data 80 4E 40
M T0:  Ch 1 Data 90 4F 64
M T0:  Ch 1 Data 80 4F 40

this is just a scale on channel 1, with NoteOn's & NoteOffs.  But I think the problem is that the MIDI.send() function is expecting  a midi type from here:

Code:
/*! Type definition for practical use (because "unsigned char" is a bit long to write.. )*/
typedef uint8_t byte;
typedef uint16_t word;

/*! Enumeration of MIDI types */
enum kMIDIType {
NoteOff               = 0x80, ///< Note Off
NoteOn                = 0x90, ///< Note On
AfterTouchPoly        = 0xA0, ///< Polyphonic AfterTouch
ControlChange         = 0xB0, ///< Control Change / Channel Mode
ProgramChange         = 0xC0, ///< Program Change
AfterTouchChannel     = 0xD0, ///< Channel (monophonic) AfterTouch
PitchBend             = 0xE0, ///< Pitch Bend
SystemExclusive       = 0xF0, ///< System Exclusive
TimeCodeQuarterFrame  = 0xF1, ///< System Common - MIDI Time Code Quarter Frame
SongPosition          = 0xF2, ///< System Common - Song Position Pointer
SongSelect            = 0xF3, ///< System Common - Song Select
TuneRequest           = 0xF6, ///< System Common - Tune Request
Clock                 = 0xF8, ///< System Real Time - Timing Clock
Start                 = 0xFA, ///< System Real Time - Start
Continue              = 0xFB, ///< System Real Time - Continue
Stop                  = 0xFC, ///< System Real Time - Stop
ActiveSensing         = 0xFE, ///< System Real Time - Active Sensing
SystemReset           = 0xFF, ///< System Real Time - System Reset
InvalidType           = 0x00    ///< For notifying errors
};
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

now, this is just getting weird.

in one sketch, I'm getting:


sketch_sep09.ino: In function 'void midiCallback(midi_event*)':
sketch_sep09:68: error: 'midi' has not been declared

for this line: 

Code:
  MIDI.send((midi::MidiType)pev->data[0], (pev->data[1]), (pev->data[2]), (pev->channel));

and in another, I get:

MIDIFile_Play.ino: In function 'void setup()':
MIDIFile_Play:188: error: 'NoteOn' was not declared in this scope
MIDIFile_Play:189: error: 'NoteOff' was not declared in this scope
 
for this line:
Code:
MIDI.send(NoteOn, 64,  255, 1);
MIDI.send(NoteOff, 64, 255 , 1);

both sketches have references to the MIDI & MIDIfile libraries.  this doesn't make sense to me.
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1285
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Just cast the data[0] parameter to midi::MidiType.

The cast should be to kMIDIType. It is actually not part of the class definition if you look in the header file, but an external enumerated type.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

that worked.  Also, I had some library issues I think I sorted out.

The code compiles, but from what I can tell, it's looping in the setup() ???

Code:
void setup() {
 

 MIDI.begin(MIDI_CHANNEL_OMNI);
//  Serial.begin(57600);
   pinMode(MIDI_ENABLE, OUTPUT);      // sets the digital pin as output
  digitalWrite(MIDI_ENABLE, HIGH);
  //  MIDI.turnThruOff();

  //   MIDI.setHandleClock ( HandleClock );


  //MIDIfile & SD card setups
  // Initialise SD
  if (!SD.begin(chipSelect, SPI_HALF_SPEED))SD.initErrorHalt();
 Serial.println("\n begin success");   //looping here?
 
 // SD.begin(chipSelect, SPI_HALF_SPEED);

  // Initialise MIDIFile
 SMF.begin(&SD);
 SMF.setMidiHandler(midiCallback);
//  SMF.setSysexHandler(sysexCallback);
MIDI.setHandleNoteOn(HandleNoteOn);
// MIDI.sendProgramChange(P,10);   

}
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's another test I performed:

take the example from each library, add the other library and upload. 

1.  Open the MIDI example, 'Basic_MIDI_IO'.  upload it, 
result:  pass

1a.  using same sketch, add a the MIDIfile library (and the SDfat library)
result:  pass

2.  Open the MIDIfile example, 'MIDIfile Play, upload it.
result:  pass

2a.  using same sketch, add the MIDI.h library to the sketch, upload it
result:  fail


The question is, what is it about test 1a that causes it not to fail, whereas test 2a is the reverse and yet it fails? 
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1285
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Stop using the serial port for prints if your using it for midi. You just cannot do that. If one library (midi) is using a resource it is unavailable to the other code.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's the code I'm testing currently;  I've commented out all the serial prints, even though I think the serial prints were only active when I set the sketch USE_MIDI to 0.  

also, the MIDIfile.h code uses serial prints in the DUMP function.  But only if it's set to 1, so it shouldn't be the issue.


thanks again for any help.



Code:
#include <MIDI.h>

// 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.

#include <SdFat.h>
#include <MIDIFile.h>
int MIDI_ENABLE = 19;
#define USE_MIDI 1

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

#define DEBUG(x)
#define DEBUGX(x)
#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 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.
#define  SD_SELECT  10

// LED definitions for user indicators
#define READY_LED 7 // when finished
#define SMF_ERROR_LED 6 // SMF error
#define SD_ERROR_LED 5 // SD error
#define BEAT_LED 6 // toggles to the 'beat'

#define 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 if that exists.
char *tuneList[] =
{
"LOOPDEMO.MID",  // simplest and shortest file
"TWINKLE.MID",
"GANGNAM.MID",
"FUGUEGM.MID",
"POPCORN.MID",
"AIR.MID",
"PRDANCER.MID",
"MINUET.MID",
"FIRERAIN.MID",
"MOZART.MID",
"FERNANDO.MID",
"SONATAC.MID",
"SKYFALL.MID",
"XMAS.MID",
"GBROWN.MID",
"PROWLER.MID",
"IPANEMA.MID",
"JZBUMBLE.MID",
};

// These don't play as they need more than 16 tracks but will run if MIDIFile.h changed
//#define MIDI_FILE  "SYMPH9.MID" // 29 tracks
//#define MIDI_FILE  "CHATCHOO.MID" // 17 tracks
//#define MIDI_FILE  "STRIPPER.MID" // 25 tracks

SdFat SD;
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);
MIDI.send((kMIDIType)pev->data[0], (pev->data[1]), (pev->data[2]) , (pev->channel));
}
//else
// Serial.write(pev->data, pev->size);
#endif
  //DEBUG("\nM T");
  //DEBUG(pev->track);
  //DEBUG(":  Ch ");
  //DEBUG(pev->channel+1);
  //DEBUG(" Data ");
  //for (uint8_t i=0; i<pev->size; i++)
 // {
// DEBUGX(pev->data[i]);
 //   DEBUG(' ');
 // }
}

void sysexCallback(sysex_event *pev)
// Called by the MIDIFile library when a system Exclusive (sysex) file event needs
// to be processed thru 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[i]);
// 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);

MIDI.begin();
//  Serial.begin(SERIAL_RATE);
 pinMode(MIDI_ENABLE, OUTPUT);      // sets the digital pin as output
  digitalWrite(MIDI_ENABLE, HIGH);
//  DEBUG("\n[MidiFile Play List]");

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

  // Initialise 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)
{
    int  err = -1;

for (uint8_t i=0; i<ARRAY_SIZE(tuneList); i++)
{
 // reset LEDs
 digitalWrite(READY_LED, LOW);
 digitalWrite(SD_ERROR_LED, LOW);

 // use the next file name and play it
 SMF.setFilename(tuneList[i]);
 err = SMF.load();
 if (err != -1)
 {
//DEBUG("\nSMF load Error ");
//DEBUG(err);
digitalWrite(SMF_ERROR_LED, HIGH);
delay(WAIT_DELAY);
 }
 else
 {
// play the file
while (!SMF.isEOF())
{
if (SMF.getNextEvent())
tickMetronome();
}

// done with this one
SMF.close();
midiSilence();

// signal finsh LED with a dignified pause
digitalWrite(READY_LED, HIGH);
delay(WAIT_DELAY);
 }
}
}
« Last Edit: December 12, 2013, 03:44:30 pm by deseipel » Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1285
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
2a.  using same sketch, add the MIDI.h library to the sketch, upload it
result:  fail

Unclear as to what a pass or fail means here. Did it fail to just compile? or upload? Did it not run? Which bit did not run?
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Compiled, uploaded.  But doesn't play the files.  When I debug, it appears to run setup over and over again.
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1285
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

This would make it stop.

Are you sure you have enough RAM to run all of this? You could be running out of memory - you only have 2kB RAM on the Arduino.

Make the list of files shorter (just one file) by commenting out the rest. This will free up the amount of RAM taken by the strings.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm not really sure by what you mean when you wrote "that would make it stop".  What would make it stop?    The debugs are commented out. 

I believe the sketch is stopping around   err = SMF.load();.   to avoid using serial, I'm placing NoteOn commands at certain points in the code and testing.  basically, I stop hearing a note at the SMF.load();
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You might be right, I ran something and it showed I only had 166 bytes of memory left .  I used the MemoryFree library and put the sketch into non-MIDI mode, added the freememory function  and then ran 

 Serial.println(freeRam());

uploaded it and looked in the serial monitor and it showed 166 after a few lines into the loop statement.  So I'm guessing that means I'm running out of memory?
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1285
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm not really sure by what you mean when you wrote "that would make it stop".  What would make it stop?

This is an infinite loop that executes if there is an error:
Code:
while (true) ;

That would make the Arduino stop, especially if you say that the setup() seems to be where the code stops.

Quote
I believe the sketch is stopping around   err = SMF.load();.   

This is actually in loop() and not in setup(), so you are contradicting previous information.

Quote
So I'm guessing that means I'm running out of memory?

It is possible. 166 bytes is not a lot and the libraries could be allocating memory. Free up memory as suggested previously and see if it works.

Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Full Member
***
Karma: 0
Posts: 120
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gotcha, thanks.  Been a long day. 
Logged

Pages: 1 [2] 3 4   Go Up
Jump to: