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

Elixir, MIDI and LiveView

Elixir, MIDI and LiveView

(Paris.Ex meetup)

Thibaut Barrère

June 18, 2019
Tweet

More Decks by Thibaut Barrère

Other Decks in Programming

Transcript

  1. Elixir, MIDI
    & LiveView

    View Slide

  2. @thibaut_barrere
    Consultant
    Ruby / Elixir / Ansible
    Kiba ETL / Kiba Pro
    Remote 100% (Charente Maritime)

    View Slide

  3. Elixir =>
    Code-Centric Digital
    Audio Workstation?
    infiniwip (tm)

    View Slide

  4. Previous episode
    https://github.com/thbar/demo-elixir-reloading-music
    Code.eval_file("music.exs")

    View Slide

  5. MIDI

    View Slide

  6. Note On
    {0x90 + channel, note, velocity}
    Note Off
    {0x80 + channel, note, release_velocity}

    View Slide

  7. Keyboard / Piano / Synthetizers
    photo by Clavia

    View Slide

  8. MIDI controllers
    photo by Novation

    View Slide

  9. Virtual Instruments (on computer)

    View Slide

  10. Virtual Instruments (on iOS)
    photo by Korg

    View Slide

  11. Lightning = Inter-Device Audio & MIDI (IDAM)
    photo by Apple

    View Slide

  12. Elixir
    Code / DRY
    Refactoring Music
    Augmented Human (theory, scales)
    Soft realtime

    View Slide

  13. brew install portmidi

    View Slide

  14. View Slide

  15. # 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})

    View Slide

  16. View Slide

  17. Computer: Note 60
    Human: WTF????

    View Slide

  18. Translation
    def note_number_to_latin_name(midi_note, middle_c \\ @default_middle_c) do
    remap_note(midi_note, @latin_names, middle_c)
    end
    defp remap_note(midi_note, names, middle_c) do
    offset = get_base_offset(middle_c)
    octave = div(midi_note + offset, 12)
    octave_note = rem(midi_note + offset, 12)
    octave_note = names |> Enum.at(octave_note)
    "#{octave_note}#{octave}"
    end
    defp get_base_offset("C4"), do: -12

    View Slide

  19. DocTests ❤
    ## Examples
    iex> MusicRef.note_number_to_latin_name(60)
    "Do4"
    iex> MusicRef.note_number_to_latin_name(78)
    "Fa#5"

    View Slide

  20. Phoenix LiveView


    Time is


    HTML? ✔

    View Slide

  21. Phoenix LiveView





    SVG? ✔

    View Slide

  22. Phoenix LiveView


    # white notes


    # black notes


    View Slide

  23. View Slide

  24. View Slide

  25. 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

    View Slide

  26. View Slide

  27. Code & Demo

    View Slide