Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Elixir, MIDI and LiveView
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Thibaut Barrère
June 18, 2019
Programming
0
370
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
520
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
870
Bootstrapping your SaaS product (with freelancing)
thbar
3
590
Prestations agiles avec Acunote et Freckle
thbar
3
570
Other Decks in Programming
See All in Programming
2年のAppleウォレットパス開発の振り返り
muno92
PRO
0
200
AI 駆動開発ライフサイクル(AI-DLC):ソフトウェアエンジニアリングの再構築 / AI-DLC Introduction
kanamasa
11
6.2k
GISエンジニアから見たLINKSデータ
nokonoko1203
0
200
【卒業研究】会話ログ分析によるユーザーごとの関心に応じた話題提案手法
momok47
0
180
副作用をどこに置くか問題:オブジェクト指向で整理する設計判断ツリー
koxya
1
570
AgentCoreとHuman in the Loop
har1101
5
210
LLM Observabilityによる 対話型音声AIアプリケーションの安定運用
gekko0114
2
410
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
440
生成AIを使ったコードレビューで定性的に品質カバー
chiilog
0
150
例外処理とどう使い分ける?Result型を使ったエラー設計 #burikaigi
kajitack
16
5.9k
Unicodeどうしてる? PHPから見たUnicode対応と他言語での対応についてのお伺い
youkidearitai
PRO
1
1k
SourceGeneratorのススメ
htkym
0
170
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
910
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
400
How to build a perfect <img>
jonoalderson
1
4.9k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
110
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
0
260
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.8k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
350
SEO for Brand Visibility & Recognition
aleyda
0
4.2k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.5k
Why Our Code Smells
bkeepers
PRO
340
58k
How to Talk to Developers About Accessibility
jct
2
120
Context Engineering - Making Every Token Count
addyosmani
9
640
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