Swing Drum

This script implements a jazz swing beat played on a drumkit. It uses a random number generator to create unique patterns for each measure.

The script makes use of the Calf FluidSynth LV2 plugin, the configuration for this plugin is defined in a separate class included here via the dofile directive:


dofile("fluidsynth.bip")

Define the class and member data:


class SwingDrum {

  drums = FluidSynth(16384)
  rand = Math.Random()
  swingPattern = null

Constructor

The class constructor creates the base pattern from a simple drum pattern written in drum tablature:


  constructor() {
    local tab = Midi.DrumTabReader()
    tab.velocity(51, "x", 64)

    swingPattern = tab.read(@"
    51|x--x-xx--x-x|
    44|---x-----x--|
    ")
  }

Scheduling

Start a method to schedule the drums for a given measure and power level:


  function schedule(m, power) {

An array of weights, one for each quarter note triplet in the measure.


    local weights = [30, 0, 40, 30, 0, 50,
                     30, 0, 40, 30, 0, 50]

Calculate a MIDI velocity level from the power level and use it for every note in the swing pattern:


    local velocity = 50 + power / 2
    for(local i = 0; i < swingPattern.size(); i++) {
      swingPattern.note(i).velocity(velocity - 10)
    }

Schedule the basic swing pattern for every bar.


    drums.schedule(swingPattern, m)

Create a MIDI note for the kick drum and schedule on beats one and three if the power level is above half (50%). Additionally schedule the kick for beats two and four if the power level is above 75%.


    local kickNote = Midi.Note(36, velocity, 1, 8)
    if(power > 50) {
      drums.schedule(kickNote, m) // beat 1
      drums.schedule(kickNote, m, 2, 4) // beat 3
    }
    if(power > 75) {
      drums.schedule(kickNote, m, 1, 4) // beat 2
      drums.schedule(kickNote, m, 3, 4) // beat 4
    }

Choose a snare type: use MIDI note 37 (snare side stick) unless the power level is above 80%, then use MIDI note 38 (snare drum).


    local snareType = power < 80 ? 37 : 38

Create a MIDI note for the snare and loop over all the triplets in the measure:


    local snareNote = Midi.Note(snareType, velocity, 1, 8)
    for(local i = 0; i < 12; i++) {

Find the chance of a snare hit by multiplying the weight for this triplet by the power percentage:


      local chance = weights[i] * power / 100

Pick a random integer in the range 1-100 and fire off the snare if the pick is below our chance probability:


      local pick = rand.integer(100) + 1
      if(pick <= chance) {
        drums.schedule(snareNote, m, i, 12)
      }
    }
  }

Audio Output

A simple function to return an Audio.Source which allows the class to connect to a mixer etc.


  function output() { return drums }
}



Complete Script

dofile("fluidsynth.bip")

class SwingDrum {

  drums = FluidSynth(16384)
  rand = Math.Random()
  swingPattern = null

  constructor() {
    local tab = Midi.DrumTabReader()
    tab.velocity(51, "x", 64)

    swingPattern = tab.read(@"
    51|x--x-xx--x-x|
    44|---x-----x--|
    ")
  }

  function schedule(m, power) {

    local weights = [30, 0, 40, 30, 0, 50,
                     30, 0, 40, 30, 0, 50]

    local velocity = 50 + power / 2
    for(local i = 0; i < swingPattern.size(); i++) {
      swingPattern.note(i).velocity(velocity - 10)
    }

    drums.schedule(swingPattern, m)

    local kickNote = Midi.Note(36, velocity, 1, 8)
    if(power > 50) {
      drums.schedule(kickNote, m) // beat 1
      drums.schedule(kickNote, m, 2, 4) // beat 3
    }
    if(power > 75) {
      drums.schedule(kickNote, m, 1, 4) // beat 2
      drums.schedule(kickNote, m, 3, 4) // beat 4
    }

    local snareType = power < 80 ? 37 : 38

    local snareNote = Midi.Note(snareType, velocity, 1, 8)
    for(local i = 0; i < 12; i++) {

      local chance = weights[i] * power / 100

      local pick = rand.integer(100) + 1
      if(pick <= chance) {
        drums.schedule(snareNote, m, i, 12)
      }
    }
  }

  function output() { return drums }
}


Tutorial IndexList of All Examples


Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.