0

I have altered some code that i found online that records and playback midi data from a midi controller. from my testing i am pretty sure that notes are being recorded from my midi controller, i have added a function(noteOn) to be able to hear the playback from a speaker that is connected to the Musical instrument shield. but when i hit the play button i hear no sound from the speaker. am i passing the right parameters to the noteOn function?

#include <MIDI.h>
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
 SoftwareSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code 
MIDI_CREATE_DEFAULT_INSTANCE();
 LiquidCrystal lcd(40, 41, 43, 44, 45, 46);
 // User interface buttons and LEDs
 #define  REC_BUTTON  13
#define  PLAY_BUTTON 12


 // Define an array of elements used to store notes
 typedef struct
{
  uint8_t  channel;
  uint8_t  pitch;
  uint8_t  velocity;
  uint16_t deltaT;    // in milliseconds
} Note;

#define  MAX_NOTE  50

Note  noteList[MAX_NOTE];
int   noteIndex = 0;     // how many notes we have stored
uint32_t  lastNoteTime;  // millis() value when last recorded a note

// State machine stuff
 #define  STATE_I    0  // Idle
 #define  STATE_I2R  1  // Idle 2 Record
 #define  STATE_R    2  // Record
 #define  STATE_R2I  3  // Record 2 Idle
 #define  STATE_I2P  4  // Idle 2 Play
 #define  STATE_P    5  // Play
 #define  STATE_P2I  6  // Play 2 Idle

 uint8_t currentState = STATE_I;
 #define  SwitchState(x)  { currentState = (x); }

 #define  NOTE_TIMEOUT  5000  // timeout in ms to automatically stop recording

  // Callback function to for recording note played
 void HandleNoteOn(byte channel, byte pitch, byte velocity) 
 { 
   if ((currentState != STATE_R) || 
      (noteIndex >= MAX_NOTE))
        return;

   // Record the note
   noteList[noteIndex].channel = channel;
   noteList[noteIndex].pitch = pitch;
   noteList[noteIndex].velocity = velocity;
   noteList[noteIndex].deltaT = millis() - lastNoteTime;

   lastNoteTime = millis();
   noteIndex++;
 }

 void setup(void) 
    { 
   analogWrite(42,20);
   lcd.begin(20, 4);
   lcd.setCursor(5,0); 
    lcd.print("Record Mode:");// Print a message to the LCD
    Serial.begin(9600);
   mySerial.begin(31250);
   pinMode(REC_BUTTON, INPUT);
   pinMode(PLAY_BUTTON, INPUT);
   // Initiate MIDI communications, listen to all channels
   MIDI.begin(MIDI_CHANNEL_OMNI);    

   // Connect the HandleNoteOn function to the library, so it is called upon reception of a NoteOn.
    MIDI.setHandleNoteOn(HandleNoteOn);  // Put only the name of the function
  }
   void CheckUserInput(void)
 {
   uint8_t           recButton = digitalRead(REC_BUTTON);
   static uint8_t    recButtonLast = LOW;
   uint8_t           playButton = digitalRead(PLAY_BUTTON);
   static uint8_t    playButtonLast = LOW;

   if (recButton != recButtonLast)
   {
     recButtonLast = recButton;

     if (recButton == HIGH)
     {
       switch (currentState)
       {
          case STATE_I:  SwitchState(STATE_I2R);  break;
         case STATE_R:  SwitchState(STATE_R2I);  break;
       }
     }
   }
    if (playButton != playButtonLast)
   {
     playButtonLast = playButton;

     if (playButton == HIGH)
     {
       switch (currentState)
       {
          case STATE_I:  SwitchState(STATE_I2P);  break;
         case STATE_P:  SwitchState(STATE_P2I);  break;
       }
     }
   }
 }
    void StateMachine(void)
  {
    static uint16_t  nextNote;

  MIDI.read();   // keep this going as fast as possible and empty buffer all the time

   switch (currentState)
   {
      case STATE_I:        // do nothing

       break;

     case STATE_I2R:      // Set up for Recording

        noteIndex = 0;
       lastNoteTime = millis();
       SwitchState(STATE_R);
       break;

      case STATE_R: // Recording
    lcd.clear();
     lcd.setCursor(5,0); 
    lcd.print("Now Recording...");
        // MIDI.read() does most of the work here through the callbacks
       // Pop out of this mode if we have a full buffer

         if ((noteIndex >= MAX_NOTE) || ((millis() - lastNoteTime) > NOTE_TIMEOUT))
          SwitchState(STATE_R2I);
       break;

      case STATE_R2I:    // Transition back to idle mode - clean up if required
     case STATE_P2I:
       SwitchState(STATE_I);
       break;

     case STATE_I2P:    // Set up for playback

       nextNote = 0;
       lastNoteTime = millis();
        SwitchState(STATE_P);
       break;

      case STATE_P:      // Play the notes back
   lcd.clear();
  lcd.setCursor(5,0); 
   lcd.print("PlayingBack...");
    if (nextNote >= noteIndex) SwitchState(STATE_P2I);  // we are done

        if ((millis() - lastNoteTime) >= noteList[nextNote].deltaT)
       {
  MIDI.sendNoteOn(noteList[nextNote].pitch, noteList[nextNote].velocity, 1);                                   //noteList[nextNote].channel);  // Send the note
             noteOn(0x90, noteList[nextNote].pitch, noteList[nextNote].velocity);
         nextNote++;
         lastNoteTime = millis();
        }
       break;
   }
   }
  void loop(void) 
 {
  int  StateR = digitalRead(REC_BUTTON);
   int  StateP = digitalRead(PLAY_BUTTON);
  lcd.setCursor(0,0);
   lcd.print(String(StateR));
  lcd.setCursor(1,0);
 lcd.print(String(StateP));
   CheckUserInput();
   StateMachine();
 }
  //Send a MIDI note-on message.  Like Pressing a piano key
 void noteOn(byte channel, byte note, byte attack_velocity) {
    talkMIDI( (0x90 | channel), note, attack_velocity);
 }
  //Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
 void talkMIDI(byte cmd, byte data1, byte data2) {
   mySerial.write(cmd);
   mySerial.write(data1);

   //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
   //(sort of: http://253.ccarh.org/handout/midiprotocol/)
   if( (cmd & 0xF0) <= 0xB0)
     mySerial.write(data2);

 }
4
  • Why are you calling both MIDI.sendNoteOn and noteOn? What is connected to what? Does the music shield work with its own example program? – CL. Apr 12 '17 at 12:57
  • MIDI.sendNoteOn was present in the original code and send messages for the midi note to be on so i left it there. i added the noteOn function to have the sound of the note play through a connected speaker .i have an Midi shield connected to the musical instrument shield which are both sitting on top of the arduino mega. yes the musical instrument works with its own example program. – Hjhk90 Apr 12 '17 at 18:47
  • What was the problem? Eg, was it lack of a template for noteOn(), ie not declaring noteOn() before calling it? Also note, instead of int StateR = digitalRead(REC_BUTTON); ...; lcd.print(String(StateR));, say lcd.print(digitalRead(REC_BUTTON)); – James Waldby - jwpat7 Apr 13 '17 at 0:36
  • @jwpat7 i left out the function that resets the chip on the musical instrument shield that's was why i wasn't getting any sound out. – Hjhk90 Apr 13 '17 at 3:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.