Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elixir, MIDI & LiveView (CodeElixir London 2019)

Elixir, MIDI & LiveView (CodeElixir London 2019)

In this talk, I demonstrate the use of Elixir, Phoenix LiveView with SVG and hot-code reloading to achieve live music coding.

Live demo at https://twitter.com/unnawut/status/1151939962855677952

Thibaut Barrère

July 18, 2019
Tweet

More Decks by Thibaut Barrère

Other Decks in Programming

Transcript

  1. Detect when I save a code file def init(args) do

    {:ok, watcher_pid} = FileSystem.start_link(args) FileSystem.subscribe(watcher_pid) def handle_info({:file_event, watcher_pid, {path, events}}, state) do do IO.puts "The file at #{path} has changed!" {:noreply, state} end
  2. Re-evaluate it at runtime (hot reloading) def handle_info({:file_event, watcher_pid, {path,

    events}}, state) do do Code.eval_file(path) {:noreply, state} end
  3. AHA MOMENT GenServer reloading keeps the state across reloads. =>

    We can keep the "current music position/tick" between reloads. defmodule Artist do use GenServer def handle_info(:tick, state) do Process.send_after(self(), :tick, @tick_period)
  4. Note On {0x90 + channel, note, velocity} Note Off {0x80

    + channel, note, release_velocity}
  5. # Start a process for MIDI event queue {:ok, pid}

    = PortMidi.open(:output, "Kontakt Virtual Input") note = 48 # C-4 velocity = 127 # Send "NOTE ON" PortMidi.write(pid, {0x90, note, velocity}) # Send "NOTE OFF" PortMidi.write(pid, {0x80, note})
  6. Phoenix LiveView <svg> <%= for note <- notes do %>

    <rect x="..." y="0" width="10" height="20" fill="<%= note.color %>"> <% end %> </svg> SVG? ✔
  7. def note_on({channel, note, velocity}, device, portmidi \\ PortMidi) do Phoenix.PubSub.broadcast(Widgets.PubSub,

    "notes", {:note_on, note}) :ok = portmidi.write(device, {0x90 + channel, note, velocity}) end