Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Web Musicでは何ができるのか / Web Music latest information
Search
OKUNOKENTARO
November 24, 2018
Technology
2
1.4k
Web Musicでは何ができるのか / Web Music latest information
FRONTEND CONFERENCE 2018の登壇にて使用した資料です。
OKUNOKENTARO
November 24, 2018
Tweet
Share
More Decks by OKUNOKENTARO
See All by OKUNOKENTARO
トレタO/X アーキテクチャ移行記 Next.js App Router化への道のり / TORETA TECH UPDATE 1
okunokentaro
5
11k
Podcastを継続する技術 / refactoradio-240119
okunokentaro
1
190
Webアプリケーション設計の第一歩は ディレクトリの整理から / Encraft 1
okunokentaro
34
10k
JSONとJSON Schemaを改めて理解する / tokyo_study
okunokentaro
9
2.4k
それでもどうしてRecoilを使うのか / Harajuku.ts Meetup Recoil
okunokentaro
19
5.6k
TypeScriptは10年でこんなに進化しました / TechFeed Experts Night 11
okunokentaro
6
1.8k
Hasura.io RDBをサクサク作る方法はARやO/RMだけじゃなくなりました/hasura-io
okunokentaro
5
690
コードには型アノテーションよりも要件アノテーションを増やせ!/harajukuts2
okunokentaro
14
6.4k
10年と3ヶ月でWebサービスを作った話 / Piyogrammer Conference 2021
okunokentaro
2
1.1k
Other Decks in Technology
See All in Technology
履歴テーブル、今回はこう作りました 〜 Delegated Types編 〜 / How We Built Our History Table This Time — With Delegated Types
moznion
16
9.5k
たかが特別な時間の終わり / It's Only the End of Special Time
watany
5
1.6k
Introduction to Sansan for Engineers / エンジニア向け会社紹介
sansan33
PRO
5
48k
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
3
21k
ページの可視領域を算出する方法について整理する
yamatai1212
0
160
技術以外の世界に『越境』しエンジニアとして進化を遂げる 〜Kotlinへの愛とDevHRとしての挑戦を添えて〜
subroh0508
1
160
モバイルゲーム開発におけるエージェント技術活用への試行錯誤 ~開発効率化へのアプローチの紹介と未来に向けた展望~
qualiarts
0
310
事業部のプロジェクト進行と開発チームの改善の “時間軸" のすり合わせ
konifar
9
3.1k
.NET 10 のパフォーマンス改善
nenonaninu
2
4.8k
Multimodal AI Driving Solutions to Societal Challenges
keio_smilab
PRO
1
120
世界最速級 memcached 互換サーバー作った
yasukata
0
160
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.3k
Featured
See All Featured
Building Applications with DynamoDB
mza
96
6.8k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
How to Think Like a Performance Engineer
csswizardry
28
2.3k
A designer walks into a library…
pauljervisheath
210
24k
Rails Girls Zürich Keynote
gr2m
95
14k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Become a Pro
speakerdeck
PRO
30
5.7k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.8k
Optimizing for Happiness
mojombo
379
70k
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.1k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.3k
Transcript
8FC.VTJDͰԿ͕Ͱ͖Δͷ͔ /PW '30/5&/%$0/'&3&/$& !PLVOPLFOUBSP
୭ w Ԟݡଠ!PLVOPLFOUBSP w ΫϨεΣΞද w ΞϓϦέʔγϣϯ ɾ ΤϯδχΞ
ԿΛ͢Δਓ w ԻָۀքͰ੍࡞ελδΦۈ w ઐֶߍͰ%5.Պߨࢣ ʢ.*%*ݕఆڃࢿ֨ॴ࣋ʣ w "OHVMBSΛ༻͍ͨେن։ൃͷઃܭίϯαϧςΟ ϯάͳͲ
w "OHVMBSϢʔβίϛϡχςΟOHLZPUPͷΦʔΨφΠβ w 8FC.VTJDΛѻ͏αʔϏεͷ্ཱͪ͛ͱ։ൃ
w ԻָۀքͰ੍࡞ελδΦۈ w ઐֶߍͰ%5.Պߨࢣ ʢ.*%*ݕఆڃࢿ֨ॴ࣋ʣ w "OHVMBSΛ༻͍ͨେن։ൃͷઃܭίϯαϧςΟ ϯάͳͲ w
"OHVMBSϢʔβίϛϡχςΟOHLZPUPͷΦʔΨφΠβ w 8FC.VTJDΛѻ͏αʔϏεͷ্ཱͪ͛ͱ։ൃ ԿΛ͢Δਓ ࠓ͜͜ͷ͠·ͤΜ
8FC.VTJDͱ
8FC.VTJD w 8FC ʢϒϥβʣ ͰԻΛѻ͏ٕज़શମʹ͍ͭͯͷ௨শ w 8FC.VTJDͱ͍͏໊শͷ༷͕ଘࡏ͢ΔΘ͚Ͱͳ͍ w ओʹɺ ͍͔ͭ͘ͷԻָ
ɾ Իؔ࿈ػثΛѻ͏"1*Λࢦ͢
8FC.VTJDϋοΧιϯ
8FC.VTJDϋοΧιϯ
8FC.VTJDϋοΧιϯ w 8FC.VTJD%FWFMPQFST+1ͱ͍͏։ൃऀίϛϡχςΟ͕ओ࠵ w ෆఆظʹ։࠵ w ".&* ʢҰൠࣾஂ๏ਓԻָిࢠࣄۀڠձʣ ͕ڠࢍ͢Δྫ͋Γ w
8FC.VTJDʹؔ͢Δٕज़Λۦͯ͠࡞Λ։ൃ͢ΔϋοΧιϯ
8FC.VTJDʹؔ͢Δٕज़ w 8FCඪ४ͷओཁͳͷͱ ͯ࣍͠ͷͭ w 8FC"VEJP"1* ʢΣϒΦʔσΟ Φ"1*ʣ w
8FC্ͰԻΛѻ͏ͨΊͷ"1* w 8FC.*%*"1* ʢΣϒϛσΟ"1*ʣ w 8FC্Ͱ.*%*ϓϩ τίϧΛ੍ޚ͢ΔͨΊͷ"1*
8FC.VTJDʹؔ͢Δٕज़ w 8FCඪ४Ͱͳ͍֤ࣾఏڙͷٕज़ͱ ͯ͠ྫ͑ʜ w ϠϚϋגࣜձࣾ70$"-0%6$&3 w ࣗಈ࡞ۂ"1* w גࣜձࣾ/55υίϞEPDPNP%FWFMPQFSTVQQPSU
w Իೝࣝ"1*ɺ Ի߹"1*ͳͲ
ͲΜͳͷ͕࡞ΕΔ ʁ w εϚʔ τσόΠεͷ͖ηϯαʔΛָͬͨثͷ։ൃ w ෳਓ͕ಉ࣌ʹૢ࡞Ͱ͖ΔԻ੍ָ࡞ΞϓϦέʔγϣϯ w ՎࢺΛೖྗͨ͠Βɺ ͦͷՎࢺʹ߹ͬͨۂΛੜͯ͘͠ΕΔπʔϧ
w Իָͱແؔͷ*P5σόΠεΛ.*%*ίϯ τϩʔϥʔͰ੍ޚ
.*%*ίϯ τϩʔϥʔͱ
8FC.*%*"1*
8FC.*%*"1* w 8$ʹͯ8% ʢ࡞ۀߘʣ ͱͳ͍ͬͯΔ"1* w ࣮ϒϥβ$ISPNFͷΈ ʢ݄࣌ʣ w
https://www.w3.org/TR/webmidi/ w 51"$"VEJP8(ʹͯ 'JSFGPY͕ରԠΛද໌ w ෳϒϥβʹΑΔ࣮ࣄྫ͕ੜ·ΕΔͷͰ ࠓޙ$3 ʢקࠂީิʣ ʹਐΉݟࠐΈ
.*%*ͱ w .VTJD*OTUSVNFOU%JHJUBM*OUFSGBDF w ిࢠָثͷԋσʔλΛػثؒͰσδλϧసૹ͢ΔͨΊͷੈքڞ௨ن֨ w ʹ·ͱΊΒΕɺ ʹൃද͞Ε༷ͨ w ϩʔϥϯ
υɺ ϠϚϋɺ ίϧάɺ ΧϫΠͳͲͷຊࠃָثϝʔΧʔΛத৺ʹ ࠃ֎ͷָثϝʔΧʔʹΑͬͯࡦఆ w ָثؒͷ௨৴Ҏ֎ʹɺ ΧϥΦέɺ ίϯαʔ τͷর໌ө૾ػثͷ੍ޚʹ ༻͞ΕΔ
.*%*ͷ࠷৽ࣄ w 5IF.*%*.BOVGBDUVSFST"TTPDJBUJPO .." ݄ɺ .*%*ن֨ͷେ෯Ξοϓσʔ τͷܭըΛൃද w ԼҐޓੑΛ࣋ͨͤͭͭɺ
Α Γݱతʹɺ ؆୯ʹར༻Ͱ͖ΔΑ ͏ͳ༷ʹ w .."ʹָثϝʔΧʔΒʹՃ͑ͯ (PPHMF "QQMFͱ͍ͬͨϒϥβϕϯμʔ "CMFUPO /BUJWF*OTUSVNFOUTͱ͍ͬͨιϑ τΣΞϝʔΧʔՃໍ
w .*%*ن্֨ͰΓ ͱ Γ ͞ΕΔσʔλͰɺ ओʹ.*%*ϝ οηʔδ͕ѻΘΕΔ w .*%*ϝ οηʔδͯ͢όΠ
τྻͰѻΘΕΔ w ϚʔΫΞοϓݴޠ+40/ͷΑ ͏ͳɺ ਓؒʹͱͬͯཧղ͍͢͠σʔλͰͳ͍ w ,CQTγϦΞϧసૹΛ࣮ݱ͢ΔͨΊͷޮԽΛ࠷༏ઌʹͨ͠ܗࣜ .*%*ϝ οηʔδͱ
.*%*ϝ οηʔδ௨৴ͷΈ .*%*ίϯ τϩʔϥʔ γϯηαΠβʔ
ʮυͷԻΛͷڧ͞Ͱ໐Βͯ͘͠Ε ʂ ʯ .*%* ϝ οηʔδ .*%*ϝ οηʔδ௨৴ͷΈ
.*%*ϝ οηʔδ௨৴ͷΈ ʮ0, ʂ ʯ ̇ ʙ
8FC.*%*"1*ͷͭͷ ଓ͞Ε͍ͯΔ.*%*ೖग़ྗͷཧ w ཧతͳػث͚ͩͰͳ͘ɺ ԾతͳσόΠεΛؚΊͯ ͦͷೖग़ྗʹର͢Δɺ .*%*ϝ οηʔδͷૹड৴
w .*%*ҰछͷΠϕϯ τۦಈͳͷͰ .*%*ϝ οηʔδΛड৴ͨ͠ͱ͖ඞָͣ͠ثΛ໐Β͢ඞཁͳ͍ w ͜ΕΛ׆༻ͯ͠.*%*ίϯ τϩʔϥʔͰඇԻָͷ*P5σόΠε੍ޚͰ͖Δ
8FC.*%*"1*ͷ͍ํ
.*%*ೖग़ྗσόΠεͷऔಘ w window.navigator.requestMIDIAccess()Λ͏ w Promise͕ฦ٫͞ΕΔ w ඇಉظղܾޙͷʹ.*%*ೖྗݩͷMapͱ.*%*ग़ྗઌͷMapؚ͕·ΕΔ (async () =>
{ const midi = await window.navigator.requestMIDIAccess(); console.log(midi.inputs); console.log(midi.outputs); })();
.*%*ग़ྗઌσόΠεͷऔಘ w .*%*ϝ οηʔδͷѼઌͱͳΔ.*%*ग़ྗઌσόΠεΛऔಘ͢Δ w outputsϓϩύςΟIterableܕͱͳ͍ͬͯΔ w Array.from(midi.outputs.values())[0]ͱ͢Ε ઌ಄ͷ.*%*ग़ྗઌ͕औಘͰ͖Δ
.*%*ϝ οηʔδΛૹ৴͢Δ w औಘͨ͠.*%*ग़ྗઌʹ.*%*ϝ οηʔδΛૹ৴͢Δʹ send()ϝ ιο υΛ༻͢Δ (async ()
=> { const midi = await window.navigator.requestMIDIAccess(); const output = Array.from(midi.outputs.values())[0]; output.send([0x90, 0x45, 0x7f]); })();
.*%*ϝ οηʔδΛड৴͢Δ (async () => { const midi = await
window.navigator.requestMIDIAccess(); const input = Array.from(midi.inputs.values())[0]; input.onmidimessage = midiEvent => { // do something }; })(); w ϒϥβͰड৴͢Δͱ͖.*%*ೖྗݩʹରͯ͠ input.onmidimessageϋϯ υϥΛ༻͢Δ
w .*%*ϝ οηʔδଟ͘ͷ߹ ϝ οηʔδ͝ͱʹόΠ τ༻͍Δ w 0x90 νϟϯωϧͷԻΛग़ͤ 0x45
ϥͷԻͰ 0x7f ͷڧ͞Ͱ w ৄ͠ ͘ ʰ8FC.*%*"1*Λѻ͏ͨΊͷ.*%*جૅࣝʱ Ͱݕࡧ https://qiita.com/okunokentaro/items/efaeb1124591e84fe9d3 .*%*ϝ οηʔδͷҙຯ
8FC"VEJP"1*
8FC"VEJP"1* w 8$ʹͯ$3 ʢקࠂީิʣ ͱͳ͍ͬͯΔ"1* w Ϟμϯϒϥβͷશ͕࣮ͯ w https://www.w3.org/TR/webaudio/ w
3&$ ʢקࠂʣ ʹ͚ͯͷ࡞ۀ͕ଓ͘
ϒϥβͰԻΛѻ͏ϨΠϠʔ"1* w ࠓޙɺ 8FC35$ 8FC93ͱ͍ͬͨଞͷ"1*ͱ࿈ܞ͠ɺ Իʹؔ͢ΔϨΠϠʔΛ୲͢Δ"1*ʹͳΔݟࠐΈ w 8FC"TTFNCMZ XBTN
ͱ࿈ܞ͢Δ༷ͷࡦఆ༧ఆ ʢਪଌʣ w 6OJUZͳͲͷήʔϜʹ͓͍ͯɺ ϛ υϧΣΞΛհͣ͞ʹ ωΠςΟ ϒ"1*Λ༻Ͱ͖ΔΑ ͏ʹ͢Δɺ ͳͲ w <audio>λάͱͷ༷ࡦఆ໘Ͱͷ࿈ܞෆे w ࠓޙɺ ԻपΓͷػೳ֦ு8FC"VEJP"1*Λલఏʹ͞Εͦ͏ ʢਪଌʣ
ϒϥβͰԻϑΝΠϧΛϩʔ υ͢Δ const reader = new FileReader(); const audioCtx =
new AudioContext(); // Web Audio API reader.onload = async readEvent => { const arrayBuffer = readEvent.target.result; const audio = await audioCtx.decodeAudioData(arrayBuffer); console.log(audio); }; window.addEventListener('drop', dragEvent => { const file = dragEvent.dataTransfer.files[0]; reader.readAsArrayBuffer(file); });
8FC"VEJP"1*ͷΠϯλϑΣʔε w 8FC"VEJP"1*ͰΧςΰϦɺ ͷΠϯλϑΣʔε͕نఆ͞Ε͍ͯΔ ͦͷҰ෦Λհ w OscillatorNode पΛࢦఆͯ͠ܗΛग़ྗɺ γϯηαΠβʔͳͲʹ͏ w
BiquadFilterNode ԻͷՃʹ༻ɺ άϥϑΟ οΫ ɾ ΠίϥΠβͷ։ൃͳͲʹ͏ w PannerNode ۭؒͰͷԻͷৼΔ͍ΛऔΓѻ͏ɺ 8FC93%ήʔϜͳͲͰ༻
"VEJP8PSLMFU w 8FC"VEJP"1*͕ఆٛ͢Δඪ४ͷΠϯλϑΣʔεͷΈ߹ΘͤͰ ࣮ݱࠔͳॲཧʹ͍ͭͯɺ αϯ υσʔλʹΞΫηεͯ͠ԋࢉ͢ΔͨΊͷΈ w ϝΠϯεϨο υͰѻͬͯ͠·
͏ ͱɺ ඳըॲཧΛ݉ͶΔεϨο υͷͨΊ ൃԻʹ͕ى͖Δ w ΦʔσΟ Φ༻ͷεϨο υͰಈ࡞͢ΔAudioWorkletΛ༻͢Δ w ͢ͰʹXBTNͱΈ߹ΘͤΔऀ͕ੈքʹଟ
%FNP http://g200kg.github.io/WebAudioDesigner/
8FC.*%*"1* ͱ 8FC"VEJP"1*
%FNP http://ryoyakawai.github.io/x-webmidi/src/hx_webmidi_01.html https://korilakkuma.github.io/X-Sound/
$44Ͱѻ͏Իͷ֓೦
ʻBVEJPʼཁૉͱͷ࿈ܞ const audioCtx = new AudioContext(); const audioEl = document.querySelector('audio');
const filter = audioCtx.createBiquadFilter(); const mediaSourceNode = audioCtx.createMediaElementSource(audioEl); mediaSourceNode.connect(filter); filter.connect(audioCtx.destination); w createMediaElementSource()Λ͏ ͜ͱͰ <audio>ཁૉͱ࿈ܞͰ͖Δ
4FMFDUPST-FWFMٙࣅΫϥε w 3FTPVSDF4UBUF1TFVEPT w ಈըԻͷ࠶ੜঢ়ଶʹؔ͢ΔٖࣅΫϥεͷ༷ w :playing :paused w 5JNFEJNFOTJPOBM1TFVEPDMBTTFT
w ࣌ܥྻΛѻ͏ٖࣅΫϥεͷ༷ w 8FC755 8FC7JEFP5FYU5SBDLT Ͱͷɺ ಡΈ্͛ಈըࣈນͰͷར༻Λఆ w :current :past :future
8FC.VTJDͷ͜Ε͔Β w 8FC"VEJP"1*ʹΑΔ ήʔϜ8FC93ʹ͓͚Δ#(.ޮՌԻͷදݱɺ 8FC35$ͰͷԻ௨৴ w 8FC.*%*"1*ʹΑΔ ଟ࠼ͳػث੍ޚɺ ԕִૢ࡞ɺ ԋͷಉظ
w ؔ࿈αʔϏεαʔ υύʔςΟ"1*ͱͷ࿈ܞͰ 8FCͰͷԻָ͞Βʹ͓͠Ζ͘ ͳΔ ʂ
·ͣ༡ΜͰΈͯ ͍ͩ͘͞ 5IBOLZPV