Tables & Waves

Step 3: Connect the Electron App to the Ableton Live

This is step 3 of the Grid+Electron+Live Tutorial.

  1. Overview & Prerequisites
  2. Stub Out the Initial Electron App
  3. Connect the Electron App to the monome grid
  4. Connect the Electron App to the Ableton Live
  5. Electron Sequencer UI
  6. Ableton Live Note Sequence Integration
  7. Multitrack Sequencer & Melodies
  8. Musical Algorithms
  9. Epilogue: What Next & Parting Thoughts

Install Dependencies & Configure Live MIDI Preferences

In step 3, the next piece of plumbing will involve establishing the first connection between the Electron app and Ableton Live, specifically receiving a MIDI clock signal from Live. To do this we will need to install a MIDI package:

$ npm install easymidi

This involves a onetime configuration of the MIDI port that will be establsihed. Do the following steps in order:

  1. Update the code for the AbletonLive class and the main.js file to the versions below.
  2. Start the Electron app with npm start
  3. Launch Live and open its MIDI preferences
  4. Find the entry named “monome in” that is established in the code below, check its box for Sync
  5. Quit the Electron app and restart it (npm start)

Now, while the Electron app is running in development mode via npm start you should see the current transport state logging to your terminal console:

$ npm start

Screenshot of the Live running in with Bar/Beat/16th notes logging to the console

Code Updates for Step 3

./main.js

There is only a single line addition. Add the daw.follow(); statement below to the post-grid connection handler.

daw.connectToGrid().then((msg) => {
  console.log(msg);
  daw.follow();
});

./app/model/ableton_live.js

This allows Live to send a MIDI clock to the Electron app. In the code below, the MIDI connection is established in the AbletonLive class's constructor. The follow() method will then process MIDI clock ticks.

The sequencer controller will have a 16th note resolution, therefore it only needs to process every 6th MIDI tick.

const easymidi   = require("easymidi");
const MonomeGrid = require("./monome_grid");


class AbletonLive {
  // For a sequencer with a 16th note pulse, 4 measures will be one "super measure" to enable a 64 step sequence
  superMeasure = 4;
  // 16n step count
  step = 0;


  constructor() {
    this.controller = new MonomeGrid(this);
    this.midiIn     = new easymidi.Input("monome in", true);
  }


  async connectToGrid() {
    const msg = await this.controller.connect();
    return msg;
  }


  async follow() {
    this.midiIn.on("clock", () => {
      this.ticks++;
      // 6 MIDI clock ticks equals a 16th note.
      if (this.ticks % 6 != 0) return;

      console.log(
        "Bar: " + (Math.floor(this.step / 16) + 1) +
        " Beat: " + (Math.floor(this.step / 4) % 4 + 1) +
        " 16th Note: " + (this.step % this.superMeasure + 1)
      );

      this.step = this.step == this.superMeasure * 16 - 1 ? 0 : this.step + 1;
    });

    this.midiIn.on("start", () => {
    });

    this.midiIn.on("position", (data) => {
      if (data.value != 0) return;

      this.ticks = 0;
      this.step  = 0;
    });
  }
}


module.exports = AbletonLive;