Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Musicでは何ができるのか / Web Music latest information

OKUNOKENTARO
November 24, 2018

Web Musicでは何ができるのか / Web Music latest information

FRONTEND CONFERENCE 2018の登壇にて使用した資料です。

OKUNOKENTARO

November 24, 2018
Tweet

More Decks by OKUNOKENTARO

Other Decks in Technology

Transcript

  1. w ԻָۀքͰ੍࡞΍ελδΦۈ຿ w ઐ໳ֶߍͰ%5.Պߨࢣ ʢ.*%*ݕఆڃࢿ֨ॴ࣋ʣ  w "OHVMBSΛ༻͍ͨେن໛։ൃͷઃܭ΍ίϯαϧςΟ ϯάͳͲ w

    "OHVMBSϢʔβίϛϡχςΟOHLZPUPͷΦʔΨφΠβ w 8FC.VTJDΛѻ͏αʔϏεͷ্ཱͪ͛ͱ։ൃ ԿΛ͢Δਓ ࠓ೔͸͜͜ͷ࿩͸͠·ͤΜ
  2. 8FC.VTJDʹؔ͢Δٕज़ w 8FCඪ४ͷओཁͳ΋ͷͱ ͯ࣍͠ͷͭ w 8FC"VEJP"1* ʢ΢ΣϒΦʔσΟ Φ"1*ʣ  w

    8FC্ͰԻ੠Λѻ͏ͨΊͷ"1* w 8FC.*%*"1* ʢ΢ΣϒϛσΟ"1*ʣ  w 8FC্Ͱ.*%*ϓϩ τίϧΛ੍ޚ͢ΔͨΊͷ"1*
  3. 8FC.*%*"1* w 8$ʹͯ8% ʢ࡞ۀ૲ߘʣ ͱͳ͍ͬͯΔ"1* w ࣮૷ϒϥ΢β͸$ISPNFͷΈ ʢ೥݄࣌఺ʣ  w

    https://www.w3.org/TR/webmidi/ w 51"$"VEJP8(ʹͯ
 'JSFGPY͕ରԠΛද໌ w ෳ਺ϒϥ΢βʹΑΔ࣮૷ࣄྫ͕ੜ·ΕΔͷͰ
 ࠓޙ$3 ʢקࠂީิʣ ʹਐΉݟࠐΈ
  4. .*%*ͱ͸ w .VTJD*OTUSVNFOU%JHJUBM*OUFSGBDF w ిࢠָثͷԋ૗σʔλΛػثؒͰσδλϧసૹ͢ΔͨΊͷੈքڞ௨ن֨ w ೥ʹ·ͱΊΒΕɺ ೥ʹൃද͞Εͨ࢓༷ w ϩʔϥϯ

    υɺ ϠϚϋɺ ίϧάɺ ΧϫΠͳͲͷ೔ຊࠃ಺ָثϝʔΧʔΛத৺ʹ
 ࠃ಺֎ͷָثϝʔΧʔʹΑͬͯࡦఆ w ָثؒͷ௨৴Ҏ֎ʹ΋ɺ ΧϥΦέɺ ίϯαʔ τͷর໌΍ө૾ػثͷ੍ޚʹ΋
 ࢖༻͞ΕΔ
  5. .*%*ͷ࠷৽ࣄ৘ w 5IF.*%*.BOVGBDUVSFST"TTPDJBUJPO .." ͸
 ೥݄ɺ .*%*ن֨ͷେ෯Ξοϓσʔ τͷܭըΛൃද w ԼҐޓ׵ੑΛ࣋ͨͤͭͭɺ

    Α Γݱ୅తʹɺ ؆୯ʹར༻Ͱ͖ΔΑ ͏ͳ࢓༷ʹ w .."ʹ͸ָثϝʔΧʔΒʹՃ͑ͯ
 (PPHMF "QQMFͱ͍ͬͨϒϥ΢βϕϯμʔ΍
 "CMFUPO /BUJWF*OTUSVNFOUTͱ͍ͬͨιϑ τ΢ΣΞϝʔΧʔ΋Ճໍ
  6. w .*%*ن্֨Ͱ΍Γ ͱ Γ ͞ΕΔσʔλͰ͸ɺ ओʹ.*%*ϝ οηʔδ͕ѻΘΕΔ w .*%*ϝ οηʔδ͸͢΂ͯόΠ

    τྻͰѻΘΕΔ w ϚʔΫΞοϓݴޠ΍+40/ͷΑ ͏ͳɺ ਓؒʹͱͬͯཧղ͠΍͍͢σʔλͰ͸ͳ͍ w ,CQTγϦΞϧసૹΛ࣮ݱ͢ΔͨΊͷޮ཰ԽΛ࠷༏ઌʹͨ͠ܗࣜ .*%*ϝ οηʔδͱ͸
  7. 8FC.*%*"1*ͷͭͷ੹຿  ઀ଓ͞Ε͍ͯΔ.*%*ೖग़ྗͷ؅ཧ w ෺ཧతͳػث͚ͩͰͳ͘ɺ Ծ૝తͳσόΠεΛؚΊͯ  ͦͷೖग़ྗʹର͢Δɺ .*%*ϝ οηʔδͷૹड৴

    w .*%*͸ҰछͷΠϕϯ τۦಈͳͷͰ
 .*%*ϝ οηʔδΛड৴ͨ͠ͱ͖ඞͣ͠΋ָثΛ໐Β͢ඞཁ͸ͳ͍ w ͜ΕΛ׆༻ͯ͠.*%*ίϯ τϩʔϥʔͰඇԻָͷ*P5σόΠε੍ޚ΋Ͱ͖Δ
  8. .*%*ϝ οηʔδΛૹ৴͢Δ w औಘͨ͠.*%*ग़ྗઌʹ.*%*ϝ οηʔδΛૹ৴͢Δʹ͸
 send()ϝ ιο υΛ࢖༻͢Δ (async ()

    => { const midi = await window.navigator.requestMIDIAccess(); const output = Array.from(midi.outputs.values())[0]; output.send([0x90, 0x45, 0x7f]); })();
  9. .*%*ϝ οηʔδΛड৴͢Δ (async () => { const midi = await

    window.navigator.requestMIDIAccess(); const input = Array.from(midi.inputs.values())[0]; input.onmidimessage = midiEvent => { // do something }; })(); w ϒϥ΢βͰड৴͢Δͱ͖͸.*%*ೖྗݩʹରͯ͠
 input.onmidimessageϋϯ υϥΛ࢖༻͢Δ
  10. w .*%*ϝ οηʔδ͸ଟ͘ͷ৔߹
 ϝ οηʔδ͝ͱʹόΠ τ༻͍Δ w 0x90 νϟϯωϧͷԻΛग़ͤ
 0x45

    ϥͷԻͰ
 0x7f ͷڧ͞Ͱ w ৄ͠ ͘͸ ʰ8FC.*%*"1*Λѻ͏ͨΊͷ.*%*جૅ஌ࣝʱ Ͱݕࡧ
 https://qiita.com/okunokentaro/items/efaeb1124591e84fe9d3 .*%*ϝ οηʔδͷҙຯ
  11. ϒϥ΢βͰԻΛѻ͏௿ϨΠϠʔ"1* w ࠓޙɺ 8FC35$ 8FC93ͱ͍ͬͨଞͷ"1*ͱ࿈ܞ͠ɺ 
 Իʹؔ͢Δ௿ϨΠϠʔΛ୲౰͢Δ"1*ʹͳΔݟࠐΈ w 8FC"TTFNCMZ XBTN

    ͱ࿈ܞ͢Δ࢓༷ͷࡦఆ༧ఆ ʢਪଌʣ  w 6OJUZͳͲͷήʔϜʹ͓͍ͯɺ ϛ υϧ΢ΣΞΛհͣ͞ʹ
 ௚઀ωΠςΟ ϒ"1*Λ࢖༻Ͱ͖ΔΑ ͏ʹ͢Δɺ ͳͲ w <audio>λάͱͷ࢓༷ࡦఆ໘Ͱͷ࿈ܞ͸ෆे෼ w ࠓޙɺ ԻपΓͷػೳ֦ு͸8FC"VEJP"1*Λલఏʹ͞Εͦ͏ ʢਪଌʣ
  12. ϒϥ΢βͰԻ੠ϑΝΠϧΛϩʔ υ͢Δ 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); });
  13. 8FC"VEJP"1*ͷΠϯλϑΣʔε w 8FC"VEJP"1*Ͱ͸ΧςΰϦɺ ͷΠϯλϑΣʔε͕نఆ͞Ε͍ͯΔ
 ͦͷҰ෦Λ঺հ w OscillatorNode
 प೾਺Λࢦఆͯ͠೾ܗΛग़ྗɺ γϯηαΠβʔͳͲʹ࢖͏ w

    BiquadFilterNode
 ԻͷՃ޻ʹ࢖༻ɺ άϥϑΟ οΫ ɾ ΠίϥΠβͷ։ൃͳͲʹ΋࢖͏ w PannerNode
 ۭؒ಺ͰͷԻͷৼΔ෣͍ΛऔΓѻ͏ɺ 8FC93΍%ήʔϜͳͲͰ࢖༻
  14. "VEJP8PSLMFU w 8FC"VEJP"1*͕ఆٛ͢Δඪ४ͷΠϯλϑΣʔεͷ૊Έ߹ΘͤͰ͸
 ࣮ݱࠔ೉ͳॲཧʹ͍ͭͯɺ 
 ௚઀α΢ϯ υσʔλʹΞΫηεͯ͠ԋࢉ͢ΔͨΊͷ࢓૊Έ w ϝΠϯεϨο υͰѻͬͯ͠·

    ͏ ͱɺ ඳըॲཧΛ݉ͶΔεϨο υͷͨΊ
 ൃԻʹ໰୊͕ى͖Δ w ΦʔσΟ Φ༻ͷεϨο υͰಈ࡞͢ΔAudioWorkletΛ࢖༻͢Δ w ͢ͰʹXBTNͱ૊Έ߹ΘͤΔ໠ऀ͕ੈքʹଟ਺
  15. ʻ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>ཁૉͱ࿈ܞͰ͖Δ
  16. 4FMFDUPST-FWFMٙࣅΫϥε w 3FTPVSDF4UBUF1TFVEPT w ಈը΍Ի੠ͷ࠶ੜঢ়ଶʹؔ͢ΔٖࣅΫϥεͷ࢓༷ w :playing :paused w 5JNFEJNFOTJPOBM1TFVEPDMBTTFT

    w ࣌ܥྻΛѻ͏ٖࣅΫϥεͷ࢓༷ w 8FC755 8FC7JEFP5FYU5SBDLT Ͱͷɺ ಡΈ্͛΍ಈըࣈນͰͷར༻Λ૝ఆ w :current :past :future