Go Down

Topic: MIDI Clock Swing/Shuffle? (Read 2265 times) previous topic - next topic

WilliamK Govinda

Guys, any idea on how to introduce Swing/Shuffle to my MIDI Clock Timer? I'm using the 16-bit timer to pulse at every 96 PPQ. Them I just check if its on a beat or not to produce notes. But how do I handle Swing/Shuffle now?

Any help would be much appreciated. I will post the Timer code in a few minutes...

Wk

WilliamK Govinda

Code: [Select]
void timerStart()
{
  TCCR1A = TCCR1B = 0;
  bitWrite(TCCR1B, CS11, 1);
  bitWrite(TCCR1B, WGM12, 1);
  timerSetFrequency();
  bitWrite(TIMSK1, OCIE1A, 1);
}

void timerSetFrequency()
{
  // Calculates the Frequency for the Timer, used by the PPQ clock (Pulses Per Quarter Note) //
  // This uses the 16-bit Timer1, unused by the Arduino, unless you use the analogWrite or Tone functions //
  #define frequency (((midiClockBPM)*(PPQ))/60)
  OCR1A = (F_CPU/ 8) / frequency - 1;
}

void timerStop(void)
{
  bitWrite(TIMSK1, OCIE1A, 0);
  TCCR1A = TCCR1B = OCR1A = 0;
}


Code: [Select]
ISR(TIMER1_COMPA_vect) { midiTimer(); }

WilliamK Govinda

And here's the complete MIDI Clock Tick, which generates all notes. Its long, I know, but so far it works even at 255 BPM and 1/64 mode.

Hint: midiClockProcessDoubleSteps is used for the 1/32 steps, as we have not just 16 x 1/16 steps, but a total of 32 x 1/32 steps. (now with V1.2.0 actually a total of 64 x 1/32 steps) Instead of 1/32 you can also chose 1/64, so you end up with 64 x 1/64 steps.

I removed the code for the 2 extra Synth Parts, so its easier to read...

Code: [Select]
void midiTimer()
{
  if (midiClockProcess || midiClockProcessDoubleSteps)
  {
    uint8_t dBB = (((DRUMTRACKS+2)*midiClockProcessDoubleSteps)+(((DRUMTRACKS+2)*2)*stepsPos));
    uint8_t dBBs = ((16*midiClockProcessDoubleSteps)+(32*stepsPos));   
    uint8_t velocity = 87+(bitRead(dmSteps[patternBufferN][DRUMTRACKS+dBB],midiClockCounter)*20)+(bitRead(dmSteps[patternBufferN][DRUMTRACKS+1+dBB],midiClockCounter)*20);
   
    for (char xdtm=0; xdtm<DRUMTRACKS; xdtm++)
    {
      if (bitRead(dmSteps[patternBufferN][xdtm+dBB],midiClockCounter) && !bitRead(dmMutes,xdtm))
      {
        sendMidiNoteOff(dmNotes[xdtm], dmChannel[xdtm]);
        sendMidiNoteOn(dmNotes[xdtm],velocity, dmChannel[xdtm]);
      }
    }
       
    midiClockProcess = 0;
    midiClockProcessDoubleSteps = 0;   
  }
 
  // Midi Clock //
  if (midiClockType == 1) midiClockCounterDivider += 2; else midiClockCounterDivider++;
  if (midiClockCounterDivider >= (12*timeScale))
  {
    midiClockProcess = 1;
    midiClockCounterDivider = 0;
    midiClockCounter++;
    if (midiClockCounter >= 16)
    {
      stepsPos++;
      if (autoSteps) { editStepsPos = !editStepsPos; if (!holdingShift) doPatternLCDupdate = 1; }
      midiClockCounter = 0;
     
      if (stepsPos >= 2)
      {
        stepsPos = 0;
        if (curMode == 1)
        {
          patternSongRepeatCounter++;
          if (patternSongNext == 0 && patternSongRepeatCounter > patternSongRepeat)
          {
            MidiClockStop();
            songNextPosition = 1;
          }     
        }
       
        checkPatternLoader();
      }
    }
  }
  else if (midiClockCounterDivider == (6*timeScale)) midiClockProcessDoubleSteps = 1;
}

WilliamK Govinda

That's the complete code, hopefully someone will get a hint on how to do it. I'm only asking as I have no clue on how, and I'm very tired already from other projects.  :smiley-red:

Wk

WilliamK Govinda

Well, I managed to get a nice Shuffle feel by doing a small hack on how I count the PPQs. So far its working nicely...

Here's some parts of the code.

Code: [Select]
  midiClockShuffleData[0][0] = 12;
  midiClockShuffleData[1][0] = 6;

void MidiShuffleUpdate()
{
  midiClockShuffleData[0][1] = 12+midiClockShuffle;
  midiClockShuffleData[1][1] = 6+midiClockShuffle;
  midiClockShuffleData[0][2] = 12-midiClockShuffle;
  midiClockShuffleData[1][2] = 6-midiClockShuffle;
}

  // Midi Clock //
  if (midiClockType == 1) midiClockCounterDivider += 2; else midiClockCounterDivider++;
  if (midiClockCounterDivider >= (midiClockShuffleData[0][midiClockShuffleCounter]*timeScale))
  {
...........
}[code]

midiClockShuffle goes from 0 to 6. At 1 and 2 you can already get a nice shuffle feeling.

Wk
[/code]

Go Up