Midi clock signals

Status
Not open for further replies.
Hello. First I want to say cheers for a great product. And also I hope I am writing in the right place. I was looking at a way of syncing my gameboy with music production software through midi. I am not sure if I am missing something but it seems not possible to read all bytes of the midi message. From what I can see the first byte is hidden by the usbMIDI.getType() function and usbMIDI.getChannel(). Is there a simple way of getting around this? Is there a way of hacking the source of the midi library?

I hope I am just being stupid here.. Also I am using teensy 2.0 if that makes any difference.

Thanks

ERik
 
OK you are in the right place, BUT have to clarify a bit your exact layout and what you want it to do if you want specific help. Also at least give us a little source code (see message IN RED above).

BUT FIRST I would direct your attention to a post on the amazing Little Scale blog.

http://little-scale.blogspot.com/2011/08/usb-midi-game-boy-sync-for-16.html <--has code, circuits

Is that what you are looking for, or is it perhaps what you are working from?

Hope that helps.
 
Sorry. I guess I wasn't clear enough. I am using teensy 2.0 in usb midi mode. A midi message normally consist of three bytes. From what I can see I can read the second and the third byte with usbMIDI.getData1() and usbMIDI.getData2(). But there seems to be no way of reading the first byte of the midi message. The only way to access parts of the first byte is through usbMIDI.getType() and usbMIDI.getChannel(). But these preset types does not cover the standard for midi clock signals.

Hope that clears it up.

[EDIT]I don't know if there is another documentation but I was using this page as information, https://www.pjrc.com/teensy/td_midi.html.[/EDIT]

Thanks

ERik
 
Last edited:
Ok, I found the source now inside the arduino folders. So that should mean that I can hack the usbMidi library.

Cheers. :)

ERik
 
Sorry. I guess I wasn't clear enough. I am using teensy 2.0 in usb midi mode. A midi message normally consist of three bytes. From what I can see I can read the second and the third byte with usbMIDI.getData1() and usbMIDI.getData2(). But there seems to be no way of reading the first byte of the midi message. The only way to access parts of the first byte is through usbMIDI.getType() and usbMIDI.getChannel(). But these preset types does not cover the standard for midi clock signals.

Hope that clears it up.

[EDIT]I don't know if there is another documentation but I was using this page as information, https://www.pjrc.com/teensy/td_midi.html.[/EDIT]

You are right, that page does not mention clock. It can be a little confusing with THREE official arduino MIDI library versions, all kinds of hacked versions out there, and USB thrown in the mix.

I don't know what the current status is, but if you look at the page I pointed you to, it says, "If you would like to edit the source code, you need to update the Teensyduino core to include MIDI Beat Clock messages. See here for more information."

Where here is:
http://little-scale.blogspot.com/2011/08/how-to-deal-with-real-time-midi-beat.html

Give that a shot? There's code to blink an LED in time with MIDI clock, so modifying and testing this simple case should take less time than lunch.
 
Thanks. I think I will hack the library. I mean I can already read the type of the clock message (as type 8), just not differentiate between the different clock messages. With this cheat just classing everything which is not one of the 7 defined types, as a clock tick, the gameboy syncs fine already. It is just not very neat.

Thanks

ERik
 
Thanks. I think I will hack the library. I mean I can already read the type of the clock message (as type 8), just not differentiate between the different clock messages.

Let me know what you come up with?

The functions available today are a hybrid of the MIDI v2.6 library from Francois Best and callbacks from another MIDI library, but without C++ subclassing, which were later adopted into MIDI v3.2.

Perhaps more functions should be added for Teensyduino 1.21 or later? I'm certainly willing to add more... it's simply not been a high priority because most projects have only needed the basic functions. If possible, I'd like to keep Teensyduino's USB MIDI functions similar to Francois's MIDI library, which is now at version 4.2.
 
Hi Paul. I think you are right that midi clock is not the most common of midi messages. I definitely do not use them everyday anyway. :) I didn't look that far into the source files but instead used the little scale implementation linked by drjohn. It seems very good to me. It properly implements a callback function for the clock messages which gives me the byte I wanted to read.

Cheers guy for the help. :) Really appreciate it.

ERik
 
Looking at the code on github the functionality has apparently been added: https://github.com/PaulStoffregen/cores/search?utf8=✓&q=setHandleRealTimeSystem, but it would be great to update the documentation (I spent quite some time looking for this and assumed I would have to hack the library).

It's true that midi clock messages are not the most commonly used ones, but they do open up quite a few possibilities. I have a foot controller powered by a teensy 2.0 that I use to control a sequencer on my computer while playing with my band on stage. Having a led light up with the tempo directly on the controller makes it possible to not always have the drummer (with the in-ear click) give the tempo at the beginning of a song. I'm also building a synth with the audio board, it would be very nice to have an arpeggiator that is synchronised with the rest.

Thank you for all these cool tools, it's amazing what they enable!
 
USBMIDI Clock slave (fixed) Pass Realtime byte to usbMIDI.getData1()

I would like to chime in on the USB MIDI Clock issue. I have to say they are a very important part of MIDI.
I use them every day and whenever I use MIDI.
Drum machines, Arpeggiators and sequencers all use them. Not all will slave. Teensy will!

I have been patching teensyduino with the following in cores/teensy3/usb_midi.c

Code:
if (type1 == 0x0F) {
		// TODO: does this need to be a full MIDI parser?
		// What software actually uses this message type in practice?
		if (usb_midi_msg_sysex_len > 0) {
			// From David Sorlien, dsorlien at gmail.com, http://axe4live.wordpress.com
			// OSX sometimes uses Single Byte Unparsed to
			// send bytes in the middle of a SYSEX message.
			sysex_byte(n >> 8);
		} else {
			// From Sebastian Tomczak, seb.tomczak at gmail.com
			// http://little-scale.blogspot.com/2011/08/usb-midi-game-boy-sync-for-16.html
			usb_midi_msg_type = 8;
			if (usb_midi_handleRealTimeSystem)
                (*usb_midi_handleRealTimeSystem)(n >> 8);
            //goto return_message;
            // From viclabs 3/12/2016 Pass Realtime byte back to usbMIDI.getData1();
            usb_midi_msg_channel = ch;
            usb_midi_msg_data1 = (n >> 8);
            return 1;
	}
}

I have only changed from the viclabs comment.
Use like this

Code:
  if (usbMIDI.read()) {
    type = usbMIDI.getType();
    d1 = usbMIDI.getData1();
    d2 = usbMIDI.getData2();
    dd = d1 + (d2 << 8);
    chnl = usbMIDI.getChannel();

    switch (type) {
      case 1:
        midiA.sendNoteOn(d1, d2, chnl);
        break;
      case 0:
        midiA.sendNoteOff(d1, d2, chnl);
        break;
      case 2:
        midiA.sendPolyPressure(d1, d2, chnl);
        break;
      case 3:
         midiA.sendControlChange(d1, d2, chnl);
        break;
      case 4:
        midiA.sendProgramChange(dd, chnl);
        break;
      case 5:
        midiA.sendAfterTouch(dd, chnl);
        break;
      case 6:
        midiA.sendPitchBend(dd, chnl);
        break;
      case 7:
         byte *  mySysExArray;
        mySysExArray = usbMIDI.getSysExArray();
        break;
      case 8:
        midiA.sendRealTime((midi::MidiType)d1);
        if (hasDinSync) {
          switch (d1) {
            case START:
              midiA.sendRealTime(midi::Start);
              break;
            case STOP:
              midiA.sendRealTime(midi::Stop);
              break;
            case CONTINUE:
              midiA.sendRealTime(midi::Continue);
              break;
            case CLOCK:
              midiA.sendRealTime(midi::Clock);
          }
        }
        break;
      default:
        break;
    }
  }

I also found that to be quick enough for the clock it pays to not use callbacks.

This will enable the teensy to follow USBMIDI clock.
I use it to drive a TR-909, Quicksilver Devilfish, and TB-303.
Din Sync, MIDI Clock and USBMIDI Clock out all from Teensy LC which is a USBMIDI Clock Slave.

I could use some direction about the right way to do this change via github. I have never done a pull request before but would be keen to know the right way to go about merging fixes so they get to the whole community. Apologies if there is already a post with this question.

Just post here is you need this for Teensy 2. The same change needs to be put in a different folder in cores, maybe with a different name from memory. I have got it working and will post on request.

Hope this helps
 
Status
Not open for further replies.
Back
Top