Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 3 of 3

Thread: Calculate Tempo from external MIDI Clock pulses.

  1. #1
    Junior Member
    Join Date
    Jan 2019
    Posts
    10

    Calculate Tempo from external MIDI Clock pulses.

    I need advice about calculating tempo from an external MIDI clock source.

    I am using my Teensy as part of a MIDI foot controller to control another MIDI device. My intention is to read an external MIDI clock via a serial MIDI IN, calculate the tempo, and send the tempo value to the MIDI device I’m controlling. The device I'm controlling does not accept external MIDI clock in but it will accept a tempo value.

    I can read the external clock, but accuracy is a problem. My tempo calculation is off as seen in the examples below.

    Example:
    Clock source 49 serial; calculated tempo 48
    Clock source 132 serial; calculated tempo 133
    Clock source 246 serial; calculated tempo 250

    The code below is what I came up with, but I’m sure there must be a better way to accomplish what I’m trying to do. Also, the full sketch I’m using about 1700 lines long and I believe the time calculation may be affected by the time it takes to run the rest of the code which varies depending on button presses and other things. The values above were calculated using the code below not the entire 1700 line sketch.


    I am not a very experienced programmer. Any suggestions would be helpful. Thank you.

    Code:
    #include <MIDI.h>
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
    unsigned long MidiClockTime = 0;
    unsigned long LastClkRead = 0;
    unsigned long extTempo = 0;
    int countClk = 0;
    unsigned long deltaT[24];
    unsigned long AvgClkTime = 0;
    unsigned long TotalTime = 0;
    unsigned long avgTime = 0;
    unsigned long oldTemp = 0;
    
    void setup() {
      Serial1.begin(31250);
      MIDI.setHandleClock(handleClock);
      MIDI.begin(MIDI_CHANNEL_OMNI);
    }
    
    void loop() {
      MIDI.read();
    }
    
    void handleClock() {
      MidiClockTime = (micros() - LastClkRead) ;
      LastClkRead = micros();
      deltaT[countClk] = MidiClockTime;
      countClk = countClk + 1;
    
      if (countClk == 24) {
        for (byte k = 2; k <= 24; k++) {
          avgTime = (deltaT[k] + deltaT[k - 1]) / 2; // find the time between 2 ticks
          TotalTime = TotalTime + avgTime;
        }
        AvgClkTime = TotalTime / 23;  // find the average difference in time between 24 ticks for better stability
        // Tempo (BPM) = (60 sec * 1/24 ticks * 10^6 microseconds)/ time between ticks in micro secs
        // minus two just because it got me closer the the clock in value
        extTempo = (2500000 / AvgClkTime) -2 ;
        TotalTime = 0;
        countClk = 0;
      }
      Serial.print("extTempo: ");
      Serial.println(extTempo);
    }

    I also get the error below when compiling and am not sure how to deal with it:

    Code:
    midiClockRead: In function 'handleClock()':
    midiClockRead:31: warning: iteration 22 invokes undefined behavior 
           avgTime = (deltaT[k] + deltaT[k - 1]) / 2; // find the time between 2 ticks
                              ^
    /var/folders/hh/fnqdklxx6z9__mzlchz0505r0000gn/T/arduino_modified_sketch_342107/midiClockRead.ino:30:24: note: containing loop
         for (byte k = 2; k <= 24; k++) {

  2. #2
    Senior Member
    Join Date
    Feb 2017
    Posts
    279
    Array indices start at zero. An array with 24 elements does not have an element #24.

  3. #3
    Junior Member
    Join Date
    Jan 2019
    Posts
    10
    Thank you!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •