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
ruby.wasm で作る MIDI コントローラー
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
nagachika
June 12, 2026
Technology
92
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ruby.wasm で作る MIDI コントローラー
松江Ruby会議12 にて発表した ruby.wasm と Web MIDI API を活用して作成した自作シーケンサー専用の MIDI コントローラーの紹介。
nagachika
June 12, 2026
More Decks by nagachika
See All by nagachika
Pure Intonation on Browser: Building a Sequencer with Ruby
nagachika
1
1k
Functional Music Composition
nagachika
1
780
怠惰なRubyistへの道 - Enumerator::Lazy の使いかた@福岡Ruby会議01
nagachika
5
2.2k
ruby trunk changes 統計版
nagachika
3
340
怠惰なRubyistへの道 - Enumerator::Lazy の使いかた
nagachika
17
7.7k
Ruby Kaja のご提案
nagachika
8
2.2k
Other Decks in Technology
See All in Technology
WebGIS AI Agentの紹介
_shimizu
0
590
AIチャットの改善から見えた、良いAI体験とは / What Constitutes a Good AI Experience: Insights from Improving AI Chat
kubode
0
130
自作お家AIエージェントスタックチャンFWで困っている所紹介
74th
0
160
デジタル・デザイン:次の50年を描く「進化する青写真」
y150saya
0
150
Hatena Engineer Seminar 37 jj1uzh
jj1uzh
0
200
“ID沼入口” - 基本とセキュリティから始める、考え続けるためのID管理技術勉強会 告知&イントロ
ritou
0
110
データレイクの「見えない問題」を可視化する
sansantech
PRO
1
240
秘密度ラベル初心者が第1歩でつまづかないための「設計・運用」ポイント
seafay
PRO
1
520
5分でわかるDuckDB Quack
chanyou0311
4
270
從開發到部署全都交給 AI:實作 AI 驅動的自動化流程
appleboy
0
180
本当の”仕事”を手放せる未来が見えた
mu7889yoon
0
200
脱SaaS!FDEを支えるプロビジョニングと分離設計
knih
0
310
Featured
See All Featured
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
From π to Pie charts
rasagy
0
220
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
400
Ethics towards AI in product and experience design
skipperchong
2
320
4 Signs Your Business is Dying
shpigford
187
22k
What does AI have to do with Human Rights?
axbom
PRO
1
2.2k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
210
WCS-LA-2024
lcolladotor
0
660
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Google's AI Overviews - The New Search
badams
0
1.1k
Transcript
দߐ3VCZձٞ SVCZXBTNͰ࡞Δ .*%*ίϯτϩʔϥʔ !OBHBDIJLB
8)0".* w !OBHBDIJLB w $3VCZ$PNNJUUFS$3VCZTFSJFTNBJOUBJOFS w SVCZUSVOLDIBOHFT w "/%1"%'VLVPLBSC w
4PVOE1SPHSBNNFS8BOOBCF
"HFOEB w ։ൃಈػ w .*%*ͷϚοϐϯά w 8FC.*%*"1* w ϒϥβͷαϙʔτঢ়گ w
ແઢରԠ w 8FC$PNQPOFOUTԽ
։ൃಈػ
QVSJ fi FETZOUI w SVCZXBTN 8FC"VEJP"1*Ͱ։ൃ͍ͯ͠Δ७ਖ਼γʔέϯαʔ w 3VCZ,BJHJͷηογϣϯͰհ w ֨ࢠਤΤσΟλͰԻΛߏ
QVSJ fi FETZOUIͷ֨ࢠਤΤσΟλ w جԻ ֨ࢠͷதԝ ͔Β9࣠ Y ɺ:࣠ Y
Y Y ͷपൺ ֨ࢠͷҐஔͰԻߴ͕ܾ·Δ w 1"%ܕͷίϯτϩʔϥʔͰೖྗ͍ͨ͠ Y Y
1BEܕͷ.*%*ίϯτϩʔϥʔ w ࢢൢͷ1BEίϯτϩʔϥʔ΄΅ͯ͢Y Y YͳͲ ۮYۮͷύου͕ஔ͞Ε͍ͯΔͷ
حYح͕ཉ͍͠ w QVSJ fi FETZOUIͷ֨ࢠΤσΟλجԻΛத৺ʹ্Լࠨӈରশ ˠحYحͷ֨ࢠʹରԠͨ͠1BEஔͷίϯτϩϥʔ͕ཉ͍͠ w ͳ͍ͳΒ࡞Δ͔͠ͳ͍ w ཧσόΠε
w QVSJ fi FETZOUIͷΑ͏ʹ8FCΛͬͯεϚϗλϒϨοτͰಈ͔͍ͤ ͍͍Μ͡ΌͶ
PEEQBE w IUUQTOBHBDIJLBHJUIVCJPPEEQBE w SVCZXBTN 8FC.*%*"1*Ͱಈ͘Yͷύουίϯτϩʔϥʔ w QVSJ fi FETZOUIͷૢ࡞ʹಛԽͨ͠.*%*Ϛοϐϯάઃఆ
.*%*Ϛοϐϯά
.*%* .VTJDBM*OTUSVNFOU%JHJUBM*OUFSGBDF w ָثͷʮԋσʔλʯΛػثؒͰ௨৴͢ΔͨΊͷن֨ w ʮԋσʔλʯ㲈ʮԻߴʯʮൃԻͷ͞ʯʮԻͷڧ͞ʯFUDʜ w ʮԋσʔλʯ㱠ʮԻσʔλʯԻͦͷͷͰͳ͍ w CZUF
CJUT ͷόΠφϦσʔλΛෳ ଟͭ͘ ·ͱΊͨͷΛ .*%*ϝοηʔδͱݺͿ w දతʹʮεςʔλενϟϯωϧʯʮϊʔτ൪߸ʯʮϕϩγςΟʯ ͷͭΛૹ৴͢Δ
.*%*ϝοηʔδͷϚοϐϯά w όΠτͷϝοηʔδΛͲ͏ղऍ͢Δ͔ϗετʹΑΔ w Ұൠతͳ.*%*ίϯτϩʔϥʔ%"8Ͱͭ·ΈεϥΠμʔΛԿͷૢ࡞ʹ ׂΓͯΔ͔ઃఆ͢Δ͜ͱ͕Ͱ͖Δ w QVSJ fi FETZOUI֨ࢠΤσΟλ༻ʹಠࣗͷεςʔλεͷׂΓͯΛߦͳ͏
QVSJ fi FETZOUIͷ.*%*Ϛοϐϯά w OPUF൪߸ CZUF Λ֨ࢠͷҐஔʹׂΓͯΔ w $POUSPM$IBOHF $$
w ࣍ݩมߋ w ΦΫλʔϒมߋ w ϚελʔϘϦϡʔϜ
8FC.*%*"1*
8FC.*%*"1*ͷجૅ w OBWJHBUPSSFRVFTU.*%*"DDFTT .*%*ར༻ͷݖݶཁ w NJEJ"DDFTTJOQVUTೖྗϙʔτϦετ w NJEJ"DDFTTPVUQVUTग़ྗϙʔτϦετ w NJEJ*OQVUPO.*%*.FTTBHFϝοηʔδड৴࣌ίʔϧόοΫ
w NJEJ0VUQVUTFOE .*%*ϝοηʔδૹ৴ w Ҏ্ɻ͏͚ͩͳΒΊͬͪΌγϯϓϧ
ϒϥβͷαϙʔτঢ়گ
8FC.*%*ͷࠔͳ w ϒϥβͷαϙʔτঢ়گ
8FC.*%*ͷࠔͳ w ϒϥβͷαϙʔτঢ়گ w 4BGBSJະαϙʔτ w J044BGBSJ'JSFGPY$ISPNF͍ͣΕະαϙʔτ w αʔυύʔςΟʔͷΞϓϦ 8FC.*%*
.*%*8FC ͋Δ͕ಈ࡞ෆ҆ఆ w "OESPJE$ISPNF0QFSBαϙʔτ'JSFGPYະαϙʔτ ະ֬ೝ
ϞόΠϧͰͷ8FC.*%*αϙʔτঢ়گ w J04΄΅ར༻ෆՄ αʔυύʔςΟʔϒϥβ͋Δ͕සൟʹΫϥογϡ w "OESPJE$ISPNFͰ҆ఆͯ͠ಈ࡞͢Δ ೦ͳ͕ΒJ1BEͰಈ࡞͠ͳ͍ "OESPJEλϒϨοτΛಋೖ
8FC.*%*"1*ར༻ͷϋʔυϧ w ϢʔβʔΞΫγϣϯ ΫϦοΫ ʹԠ͢ΔΠϕϯτத͔͠ॳظԽͰ͖ͳ͍ w Ϣʔβʔͷ֬ೝμΠΞϩάͰͷೝՄ͕ඞਢ ϚΠΫΧϝϥͱಉ༷ w
ޡͬͯڋ൱͢ΔͱϦηοτ͢Δͷ͕ࠔ "OESPJE൛$ISPNFͰαΠτຖ ೝՄϦετʹ.*%*͕ग़ݱ͠ͳ͍ͨΊۙͷαΠτใશআ͕ඞཁ w 5-4ଓ͕ඞਢ ͘͠DISPNFTFUUJOHT͔Βྫ֎ొ w 64#έʔϒϧଓ࣌ʹຖճ༻్Λࢦఆ͢Δඞཁ͕͋Δ
ແઢରԠ
ແઢଓରԠ w 8FC#MVFUPPUI"1* #MVFUPPUI.*%* w ϞόΠϧଆͰೝࣝͤ͞Δ͜ͱ͕Ͱ͖ͣஅ೦ w 8FC4PDLFU .*%**"$υϥΠό w
1SPT.*%*ͷ͑ͳ͍J04 J1BE Ͱ͑Δ w $POT8FC.*%*"1*Λͬͯͳ͍ʜʜ ίϯτϩʔϥʔଆ
8FC4PDLFU .*%**"$υϥΠό w .*%**"$υϥΠόNBD04্Ͱ.*%*৴߸Λհ͢ΔԾσόΠε 4PVOE fl PXFSͷ.*%*൛ͱ͍͑Θ͔ΔਓʹΘ͔Δ Bridge server odd-pad
purified- synth 8FC4PDLFU .*%*ϝοηʔδ
8FC$PNQPOFOUTԽ
8FC$PNQPOFOUTԽ w QVSJ fi FETZOUIͰը໘ίϯϙʔωϯτ)5.- +4Ͱॻ͍ͨ w 8FC$PNQPOFOUT w 3FBDU7VFͷΑ͏ʹ+4ͰΧελϜίϯϙʔωϯτΛఆٛͰ͖Δ
w SVCZXBTNΛར༻ͯ͠3VCZͷΫϥεͰίϯϙʔωϯτ͕ॻ͚ͦ͏
8FC$PNQPOFOUTԽ w ͜Μͳײ͡Ͱ8FC$PNQPOFOUϞδϡʔϧΛఆٛ module WebComponent module ClassMethods def register(tag_name) ruby_class_name
= name js_code = <<~JS (() => { class RubyComponent extends HTMLElement { connectedCallback() { const id = App.eval(` inst = #{ruby_class_name}.new id = WebComponent::WC_REGISTRY.size WebComponent::WC_REGISTRY[id] = inst inst.connected_callback(this_elem) `).toJS(); this.__rubyId = id; } } customElements.define('#{tag_name}', RubyComponent); })(); JS JS.eval(js_code) end end end
8FC$PNQPOFOUTԽ w 8FC$PNQPOFOUΛJODMVEFͯ͠ίϯϙʔωϯτΫϥεΛఆٛ class PadGrid include WebComponent def connected_callback(js_element) @element
= js_element render_grid attach_events end def render_grid doc = JS.global[:document] @grid = doc.call(:createElement, "div") @grid[:className] = "grid" VIEW_YS.reverse_each do |y| VIEW_XS.each do |x| btn = doc.call(:createElement, "button") btn[:dataset][:x] = x btn[:dataset][:y] = y btn[:textContent] = note.to_s @grid.call(:appendChild, btn) end end @shadow.call(:appendChild, @grid) end
ࠓޙͷల
ࠓޙͷల w PEEQBE୯ମͰԻΛ໐Β͍ͨ͠ w ιϯάػೳ γʔέϯαʔػೳΛ͚͍ͨ w ࣗಈϘΠγϯά ԻߴͷΦΫλʔϒࣗಈௐ
w ʜʜ͋ΕɺQVSJ fi FETZOUI͍Βͳ͍ࢠ w ࡞Γ͍ͨͷ͕ͲΜͲΜ༙͍ͯ͘Δ