Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Elixir, MIDI and LiveView
Search
Thibaut Barrère
June 18, 2019
Programming
0
360
Elixir, MIDI and LiveView
(Paris.Ex meetup)
Thibaut Barrère
June 18, 2019
Tweet
Share
More Decks by Thibaut Barrère
See All by Thibaut Barrère
Kiba ETL: feedback on OSS / open-core sustainability for a Ruby gem
thbar
0
120
Elixir, MIDI & LiveView (CodeElixir London 2019)
thbar
0
1.1k
Kiba ETL v2 - RubyKaigi 2018
thbar
4
1.9k
Elixir hot-reloading & MIDI events generation
thbar
1
510
De Rails à Phoenix - retour d'expérience sur une réécriture d'application SaaS
thbar
3
2.3k
Processing data with Ruby and Kiba ETL
thbar
0
230
Retour d'expérience sur le bootstrapping de WiseCash (produit SaaS)
thbar
0
860
Bootstrapping your SaaS product (with freelancing)
thbar
3
580
Prestations agiles avec Acunote et Freckle
thbar
3
560
Other Decks in Programming
See All in Programming
AI時代もSEOを頑張っている話
shirahama_x
0
230
CloudNative Days Winter 2025: 一週間で作る低レイヤコンテナランタイム
ternbusty
7
1.9k
堅牢なフロントエンドテスト基盤を構築するために行った取り組み
shogo4131
6
1.9k
Google Antigravity and Vibe Coding: Agentic Development Guide
mickey_kubo
2
130
俺流レスポンシブコーディング 2025
tak_dcxi
13
7.7k
CSC305 Lecture 17
javiergs
PRO
0
270
AIコーディングエージェント(NotebookLM)
kondai24
0
120
AWS CDKの推しポイントN選
akihisaikeda
1
240
モダンJSフレームワークのビルドプロセス 〜なぜReactは503行、Svelteは12行なのか〜
fuuki12
0
190
開発に寄りそう自動テストの実現
goyoki
1
360
『実践MLOps』から学ぶ DevOps for ML
nsakki55
2
550
dnx で実行できるコマンド、作ってみました
tomohisa
0
130
Featured
See All Featured
Fireside Chat
paigeccino
41
3.7k
Facilitating Awesome Meetings
lara
57
6.7k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Practical Orchestrator
shlominoach
190
11k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.3k
The Cost Of JavaScript in 2023
addyosmani
55
9.3k
Music & Morning Musume
bryan
46
7k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
How GitHub (no longer) Works
holman
316
140k
Building an army of robots
kneath
306
46k
Transcript
Elixir, MIDI & LiveView
@thibaut_barrere Consultant Ruby / Elixir / Ansible Kiba ETL /
Kiba Pro Remote 100% (Charente Maritime)
Elixir => Code-Centric Digital Audio Workstation? infiniwip (tm)
Previous episode https://github.com/thbar/demo-elixir-reloading-music Code.eval_file("music.exs")
MIDI
Note On {0x90 + channel, note, velocity} Note Off {0x80
+ channel, note, release_velocity}
Keyboard / Piano / Synthetizers photo by Clavia
MIDI controllers photo by Novation
Virtual Instruments (on computer)
Virtual Instruments (on iOS) photo by Korg
Lightning = Inter-Device Audio & MIDI (IDAM) photo by Apple
Elixir Code / DRY Refactoring Music Augmented Human (theory, scales)
Soft realtime
brew install portmidi
None
# 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})
None
Computer: Note 60 Human: WTF????
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
DocTests ❤ ## Examples iex> MusicRef.note_number_to_latin_name(60) "Do4" iex> MusicRef.note_number_to_latin_name(78) "Fa#5"
Phoenix LiveView <div> <p> Time is <%= @time %> </p>
</div> HTML? ✔
Phoenix LiveView <svg> <%= for note <- notes do %>
<rect x="..." y="0" width="10" height="20" fill="<%= note.color %>"> <% end %> </svg> SVG? ✔
Phoenix LiveView <svg> <g> # white notes </g> <g> #
black notes </g> </svg>
None
None
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
None
Code & Demo