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で音を視る
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
ydah
June 06, 2026
Technology
470
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Rubyで音を視る
松江Ruby会議12「Rubyで音を視る」の発表スライド
https://matsue.rubyist.net/matrk12/
#matrk12
ydah
June 06, 2026
More Decks by ydah
See All by ydah
Liberating Ruby's Parser from Lexer Hacks
ydah
2
3.1k
ルールルルルルRubyの中身の予備知識 ── RubyKaigiの前に予習しなイカ?
ydah
1
910
計算機科学をRubyと歩む 〜DFA型正規表現エンジンをつくる~
ydah
3
860
進捗
ydah
2
330
Joy with 3D Graphics Using Ruby
ydah
1
150
構文解析器入門
ydah
7
3.1k
Regional.rb and the Kyoto City
ydah
0
68
LRパーサーはいいぞ
ydah
7
2k
Ruby on Railroad: The Power of Visualizing CFG
ydah
0
1.5k
Other Decks in Technology
See All in Technology
不要なレビューをAIにまかせて AIコーディングの環境改善を加速した
shoota
1
250
コミュニティの有益性 ~JAWS Days 2026 での体験を通して~ / The Benefits of a Community ~Through My Experience at JAWS Days 2026~
seike460
PRO
0
270
自宅LLMの話
jacopen
1
710
「軸足」は 固定しなくていい - 熱量と強みで描く、しなやかなキャリアの形
kakehashi
PRO
1
230
スタートアップにAmazon EKSは早すぎる? マルチプロダクト戦略を加速する Platform Engineeringの実践 / Is Amazon EKS Too Soon for Startups? Practical Platform Engineering to Accelerate a Multi-Product Strategy
elmodev09
1
1.7k
コミットの「なぜ」を読む
ota1022
0
110
ロボティクスの技術 / Robotics Technology
ks91
PRO
0
130
[AWS Summit Japan 2026]迷っているあなたへ_小さな一歩が、やがて自分を助けてくれる
sh_fk2
1
380
Bucharest Tech Week 2026 - Reinventing testing practices in the AI era
edeandrea
PRO
1
170
時期が悪い!それでもRaspberry Piを買って遊んで活用するには / 20260627-osc26do-rpi-jikigawarui
akkiesoft
0
700
Oracle AI Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
4
3k
SONiCで構築・運用する生成AI向けパブリッククラウドネットワーク ~実装編~
sonic
0
330
Featured
See All Featured
Building Applications with DynamoDB
mza
96
7.1k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
430
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Docker and Python
trallard
47
3.9k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
180
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
72
40k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
780
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
610
Transcript
2026/06/06 Ruby 12 Ruby seeing sound with ruby Yudai Takada,
ydah
None
None
None
None
None
Otsu City Traditional Performing Arts Hall Saturday, July 18, 2026
None
None
None
None
None
None
2026/06/06 Ruby 12 Ruby seeing sound with ruby Yudai Takada,
ydah
None
None
vizcore https://github.com/ydah/vizcore
Vizcore visualize( ) × core( ) Audio-reactive visuals Ruby DSL
Ruby scene renderer
2D/3D OpenGL
None
None
None
None
1
3
PCM samples Mic / File samples Array<Float> [ 0.0012, 0.0031,
-0.0028, . . . ]
None
Sample Window tick window 1024 60fps tick sample 圧
Samples RMS amplitude Sample RMS 夏 圧 0 [0.5, -0.5,
0.5, -0.5] (0.5 + -0.5 + 0.5 + -0.5) / 4 = 0 RMS = 1 N N ∑ i=1 x2 i
Samples FFT magnitudes / peak_frequency FFT 圧 WN = e−2πi/N
Ek = N/2−1 ∑ m=0 x2m Wkm N/2 Ok = N/2−1 ∑ m=0 x2m+1 Wkm N/2 Xk = Ek + Wk N Ok Xk+N/2 = Ek − Wk N Ok (k = 0,1,…, N 2 − 1)
magnitudes BandSplitter sub / low / mid / high FFT
Vizcore sub, low, mid, high sub: 20Hz . . 60Hz low: 60Hz . . 250Hz mid: 250Hz . . 4000Hz high: 4000Hz . . 20000Hz
Samples frame energy BeatDetector beat FFT beat beat frame 圧
E = 1 N N ∑ i=1 x2 i
beat beat_pulse beat boolean frame true 1 frame beat 圧
1.0 beat frame 0.86 長
beat history BPMEstimator bpm / beat_phase / bar_phase BPM beat
frame lag BPM beat beat beat = beat_pulse = bpm = beat_phase = bar_phase = bpm = 60.0 * frame_rate / best_lag
bands + onset drums con fi dence 圧 band onset
kick = sublow_strength * onset # sub/low ͷڧ͞ × onset snare = mid_strength * onset # mid ͷڧ͞ × onset hihat = high_strength * onset # high ͷڧ͞ × onset
magnitudes / spectrum spectral features FFT Spectral features FFT 圧
amplitude bands spectral features centroid: / rollo ff : / fl atness: / fl ux: /
raw features smoother audio features frame を EMA EMAt =
αxt + (1 − α)EMAt−1 amplitude: @sm.smooth(:amplitude, normalized[:amplitude]) bands: @sm.smooth_hash(normalized[:bands], namespace: :bands) fft: @sm.smooth_array(normalized[:fft], namespace: :fft)
amplitude bass / low high / treble beat beat_pulse bpm
/ phase spectral_* / / / / / を 長
None
audio features MappingResolver layer params map beat_pulse, to: :radius, gain:
160.0, min: 56, max: 164, attack: 1.0, release: 0.2
beat beat_pulse map beat_pulse, to: :radius, gain: 100, min: 50,
max: 150
beat map beat_pulse, to: :radius, gain: 100, min: 50, max:
150 100
beat map beat_pulse, to: :radius, gain: 100, min: 50, max:
150 50 150
beat map beat_pulse, to: :radius, gain: 100, min: 50, max:
150 radius
layer params audio_frame audio scene layers audio frame { “audio”:
{ "amplitude": 0.42, "beat": true, "beat_pulse": 1.0, "bands": { "low": 0.8 } }, "scene": { "name": "main", "layers": [ { "name": "rings", "params": { "radius": 140 } …
audio_frame WebSocket frontend WebGL renderer Frontend audio_frame Ruby Runtime Browser
Renderer (WebGL Runtime) Web Socket
6/4
BGM
None
None
50 6 4
2026/06/06 Ruby 12 Ruby seeing sound with ruby Yudai Takada,
ydah
圧 母 /
母
母 母 F1 / F2 spectral centroid low / mid
/ high ratio
F1/F2 母 F 圧 圧 : : : / :
:
母 0.0 1.0 1 F1 F2 母
None
/ / 圧 圧 burst fl atness ZCR nasal high
ratio
burst amplitude_delta = [ current[:amplitude] - previous[:amplitude], # લϑϨʔϜ͔ΒͷԻྔ૿Ճ 0.0
].max burst_strength = [ current[:onset], # Իͷ্ཱ͕ͪΓ current[:spectral_flux], # εϖΫτϧมԽྔ current.dig(:onsets, :mid), # தҬͷ্ཱ͕ͪΓ current.dig(:onsets, :high), # ߴҬͷ্ཱ͕ͪΓ amplitude_delta, # Իྔͷ૿Ճྔ recent_onset_max # ۙ૭ͷ࠷େ্ཱ͕ͪΓ ].max
spectral fl atness s_score = weighted_average([ high_ratio, # ߴҬͷڧ͞ flatness,
# ϊΠζͬΆ͞ zcr, # ܗͷࡉ͔͍༳Ε centroid # Իͷ໌Δ͞ ]) n_score = weighted_average([ nasal_score, # ඓԻͬΆ͞ 1.0 - high_ratio, # ߴҬ͕গͳ͍ low_mid_ratio, # ʙதҬͷڧ͞ 1.0 - zcr # ༳Ε͕গͳ͍ ])
attack feature attack = { strength: attack[:attack_strength], # ग़ͩ͠ͷڧ͞ centroid:
attack[:centroid_norm], # ग़ͩ͠ͷ໌Δ͞ high: attack[:high_ratio], # ߴҬͷڧ͞ low: attack[:low_ratio], # Ҭͷڧ͞ flatness: attack[:spectral_flatness],# ϊΠζͬΆ͞ zcr: attack[:zero_crossing_rate], # ࡉ͔͍༳Ε f1 : attack[:f1_frequency], # F1 ͬΆ͍ࢁ f2 : attack[:f2_frequency], # F2 ͬΆ͍ࢁ nasal: attack_nasal_score # ඓԻͬΆ͞ }
母 × kana_score = [ vowel_score * 0.55, # ԻΒ͠͞
consonant_score * 0.35, # ࢠԻΒ͠͞ burst_bonus * 0.10 # ग़ͩ͠ͷิਖ਼ ].sum candidate = { text: kana_table[consonant][vowel], # ͔ͳจࣈ vowel: vowel, # ਪఆԻ consonant: consonant, # ਪఆࢠԻ conf i dence: kana_score # ީิͷࣗ৴ }
None
vizcore Ruby ォ Ruby
$whoami ォ ydah ( ) SmartHR Ruby 西 Ruby Ruby
( 西 ) 西 圧 OSS 2