Slide 1

Slide 1 text

Elixir, MIDI & LiveView

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

MIDI

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Keyboard / Piano / Synthetizers photo by Clavia

Slide 8

Slide 8 text

MIDI controllers photo by Novation

Slide 9

Slide 9 text

Virtual Instruments (on computer)

Slide 10

Slide 10 text

Virtual Instruments (on iOS) photo by Korg

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

brew install portmidi

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Computer: Note 60 Human: WTF????

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Phoenix LiveView

Time is <%= @time %>

HTML? ✔

Slide 21

Slide 21 text

Phoenix LiveView SVG? ✔

Slide 22

Slide 22 text

Phoenix LiveView

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

Code & Demo