Tagalog (Wikang Tagalog) translation by Robert Alexander (you can also view the original English article)



Ang
Web Audio API ay isang modelong lubusang hiwalay mula sa <audio> tag.
Ito ay isang JavaScript API para sa
pagproseso at pagsintesis ng audio para sa web. Ang layunin ng
API na ito ay isama ang lahat ng kapabilidad na makikita sa mga modernong laro
at ilan sa mga paghahalo, pagpoproseso, at pagsasala ng mga gawain na ginamit
sa mga karaniwang desktop na mga aplikasyon.
Ano ang Aming Ginagawa
Ang aming demo sa itaas ay naglalaman ng tatlong mga input sa radyo na kapag pinili ay papaganahin ang nararapat na audio na sinasanggunihan. Kapag may napiling channel, papaganahin ito ng aming audio at ipapakita ang frequency graph.
Hindi ko ipapaliwanag ang bawat linya ng kowd sa demo; subalit, ipapaliwanag ko ang mga pangunahing impormasyon na tumutulong sa pagpapakita ng audio source at ng kanyang frequency graph. Para magsimula, kailangan natin ng maliit na markup.
Ang Markup
<canvas id="oscilloscope"></canvas>
Ang pinakaimportanteng bahagi ng markup ay
ang canvas
, na siyang elemento na magpapakita ng ating oscilloscope. Kapag
hindi ka pamilyar sa canvas
, iminumungkahi ko na basahin mo ang artikulo na may
pamagat na "Isang Panimula sa Pagtatrabaho Gamit ang Canvas."
Dahil nakahanda na ang antas ng pagpapakita ng graph, kailangan na nating gawin ang audio.
Paggawa ng Audio
Magsisimula tayo sa pamamagitan ng paglalarawan sa ilan sa mga mahahalagang mga bagay para sa audio context at gain. Ang mga bagay na ito ay gagamitin bilang sangguni sa isang punto sa kowd.
let audioContext, masterGain;
Kinakatawan ng audioContext
ang
audio-processing graph (isang kumpletong paglalarawan sa audio signal
processing network) na ginawa mula sa mga audio module na sama-samang kinawing. Ang bawat isa ay kinakatawan ng AudioNode
,
at kapag pinagsama, nakakagawa sila ng audio routing graph. Kinokontrol ng
audio context ang parehong paggawa ng node(s) na nilalaman nito at ang
pagsasagawa ng pagproseso ng audio at decoding.
Ang AudioContext
ay dapat ginagawa bago ang
ibang bagay, sapagkat lahat ay nangyayari sa loob ng context.
Tinatanggap ng aming masterGain
ang input
ng isa o higit pang mga audio source at taga-output ng volume ng audio, na dati
ng na-adjust sa gain sa antas na tinukoy ng node ng GainNode.gain
a-rate
parameter. Pwede mong isipin ang master gain bilang
volume. Ngayon gagawa tayo ng gawain na papayagan ang playback ng browser.
function audioSetup() { let source = 'https://ice1.somafm.com/seventies-128-aac'; audioContext = new (window.AudioContext || window.webkitAudioContext)(); }
Magsisimula ako
sa pamamagitan ng paglalarawan ng source
variable na gagamitin para pagsangguni
sa audio file. Sa kasong ito gumagamit ako ng URL sa isang
serbisyong streaming, pero pwede ring audio file. Inilalarawan ng audioContext
line ang audio
object at ito ang context na tinalakay natin dati. Sinuri ko rin ang
compatibility gamit ang WebKit
prefix, pero ang suporta ay ginagamit na
ngayon puwera sa IE11 at Opera Mini.
function audioSetup() { masterGain = audioContext.createGain(); masterGain.connect(audioContext.destination); }
Dahil kumpleto na ang ating pangunahing
hakbang, kailangan na nating gumawa at kumonekta sa masterGain
papunta sa audio
destination. Para sa trabahong ito, gagamitin natin ang connect()
na
pamamaraan, na siyang papayagan kang kumonekta sa isa sa mga output ng node
papunta sa pinupuntirya.
function audioSetup() { let song = new Audio(source), songSource = audioContext.createMediaElementSource(song); songSource.connect(masterGain); song.play(); }
Ang song
variable ay gumagawa ng bagong
audio object gamit ang Audio()
constructor. Kakailanganin mo ang audio object
para ang context ay may source para sa playback para sa mga tagapakinig.
Ang songSource
variable ay ang nagpapagana
sa audio at kung saan natin ipapasa ang ating audio source. Sa pamamagitan ng
paggamit ng createMediaElementSource()
, pwedeng paganahin ang audio at ibahin
ito kapag gusto. Ang huling variable ang kumokonekta sa
ating audio source papunta sa master gain (volume). Ang huling linya ng
song.play()ay
ang hudyat para sa aktwal na pagbigay ng permiso para paganahin
ang audio.
let audioContext, masterGain; function audioSetup() { let source = 'http://ice1.somafm.com/seventies-128-aac'; audioContext = new (window.AudioContext || window.webkitAudioContext)(); masterGain = audioContext.createGain(); masterGain.connect(audioContext.destination); let song = new Audio(source), songSource = audioContext.createMediaElementSource(song); songSource.connect(masterGain); song.play(); } audioSetup();
Ito ang aming huling resulta na naglalaman ng lahat ng mga linya ng kowd na tinalakay natin hanggang sa puntong ito. Sinigurado ko na gagawa tayo ng tawag sa gawain sa huling linya. Susunod, gagawa tayo ng audio wave form.
Paggawa ng Audio Wave
Para maipakita ang frequency wave para sa napiling audio source, kailangan nating gawin ang wave form.
const analyser = audioContext.createAnalyser(); masterGain.connect(analyser);
Ang unang sangguni sa createAnalyser()
ay
inilalabas ay audio time at frequency data para makagawa ng mga data
visualization. Magagawa ng pamamaraan na ito ang AnalyserNode na siyang
nagpapasa ng audio stream mula sa input papunta sa output, pero pinapayagan
kang makakuha ng nagawang datos, iproseso ito, at gumawa ng mga audio
visualization na may eksaktong isang input at isang output. Ang analyser node ay ikokonekta sa master
gain na siyang output ng ating signal path at nagbibigay ng abilidad para
masuri ang source.
const waveform = new Float32Array(analyser.frequencyBinCount); analyser.getFloatTimeDomainData(waveform);
Itong Float32Array()
constructor ay
kumakatawan sa linya ng 32-bit floating point number. Ang frequencyBinCount
property ng AnalyserNode
interface ay isang unsigned long value na kalahati ng
sukat ng FFT (Fast Fourier Transform). Sa pangkalahatan katumbas nito ang numero
ng mga datos na kailangan mong gamitin sa visualization. Ginamit namin ang
pamamaraan na ito para makakolekta ng aming frequency data nang paulit-ulit.
Ang huling pamamaraan getFloatTimeDomainData
ang kumokopya sa kasalukuyang waveform, o time-domain data, sa
Float32Array
na ipinasa dito.
function updateWaveform() { requestAnimationFrame(updateWaveform); analyser.getFloatTimeDomainData(waveform); }
Itong kabuuang halaga ng datos at
pagpoproseso ay gumagamit ng requestAnimationFrame()
para makakolekta ng time
domain data nang paulit ulit at makakuha ng
"oscilloscope style" output ng kasalukuyang audio input.
Gagawa din ako ng isa pang tawag getFloatTimeDomainData()
sapagkat kailangan
nitong palaging na-update sapagkat dinamiko ang audio source.
const analyser = audioContext.createAnalyser(); masterGain.connect(analyser); const waveform = new Float32Array(analyser.frequencyBinCount); analyser.getFloatTimeDomainData(waveform); function updateWaveform() { requestAnimationFrame(updateWaveform); analyser.getFloatTimeDomainData(waveform); }
Ang pagsasama ng lahat ng mga kowd na natalakay
natin ay nagresulta sa kabuuang gawain sa itaas. Ang tawag sa gawain na ito ay
ilalagay sa loob ng audioSetup
na gawain sa ibaba ng song.play().
Dahil nasa tamang lugar ang wave form, kailangan parin nating iguhit ang
impormasyon na ito sa screen gamit ang elementong canvas
, at ito ang susunod na
bahagi ng ating talakayan.
Pagguhit ng Audio Wave
Ngayon na nagawa na natin ang waveform at
mayroon na tayong datos na kailangan, kailangan nating iguhit ito sa screen;
dito na ipinapakilala ang elementong canvas.
function drawOscilloscope() { requestAnimationFrame(drawOscilloscope); const scopeCanvas = document.getElementById('oscilloscope'); const scopeContext = scopeCanvas.getContext('2d'); }
Ipinapakita ng
kowd sa itaas ang elementong canvas
para maisangguni ito sa ating gawain. Ang tawag sa requestAnimationFrame
sa
itaas ng gawain na ito ang siyang magiiskedyul ng susunod na animation frame. Ito ay nilagay nang una para malapit tayo
sa 60FPS.
function drawOscilloscope() { scopeCanvas.width = waveform.length; scopeCanvas.height = 200; }
Naisagawa ko ang pangkaraniwang estilo na
siyang guguhit ng lapad at taas ng canvas
. Iisa lamang ang halaga ng taas,
habang ang lapad ang haba ng wave form na nagawa ng audio source.
function drawOscilloscope() { scopeContext.clearRect(0, 0, scopeCanvas.width, scopeCanvas.height); scopeContext.beginPath(); }
Ang clearRect(x, y, width, height)
pamamaraan ang siyang maglilinaw ng mga dati ng naguhit na nilalaman
para patuloy nating maiguhit ang frequency graph. Kailangan mo ring siguraduhin
ang beginPath()
bago magsimula sa bagong frame pagkatapos ng pagtawag ng
clearRect().
Ang pamamaraan na ito ay nagsisimula sa
bagong landas sa pamamagitan ng listahan na walang laman at lahat ng maliliit
na mga landas. Ang panghuli ay ang loop para patakbuhin ang mga datos na nakuha
para patuloy nating maiguhit itong frequency graph sa screen.
function drawOscilloscope() { for(let i = 0; i < waveform.length; i++) { const x = i; const y = ( 0.5 + (waveform[i] / 2) ) * scopeCanvas.height; if(i == 0) { scopeContext.moveTo(x, y); } else { scopeContext.lineTo(x, y); } } scopeContext.stroke(); }
Itong loop sa itaas ang nangguhit ng ating
wave form sa elementong canvas
. Kapag ni-log natin ang wave form length sa
console (habang pinapagana ang audio), maguulat ito ng 1024 nang paulit-ulit. Sa pangkalahatan
ito katumbas ng numero ng datos na kailangan mong paganahin para sa
visualization. Kapag natatandaan
mo mula sa nakaraang seksyon para sa paggawa ng wave form, nakuha nating ang
halaga mula Float32Array(analyser.frequencyBinCount)
. Ganito nating naisangguni ang 1024 halaga na gagamitin sa
looping.
Ang moveTo()
na pamamaraan ang maglilipat
ng punto ng simula mula sa bagong sub-path papunta sa na-update (x, y)
na mga
coordinate. Ang lineTo()
na pamamaraan ang kumokonekta sa huling punto sa
sub-path sa x, y
na mga coordinate gamit ang tuwid na linya (pero hindi niya
aktwal na ginuguhit). Ang huling ay ang pagtawag ng stroke()
na
binigay ng canvas
para maiguhit nating nang aktwal ang frequency line. Iiwan ko
ang opsyon na naglalaman ng math bilang hamon sa nagbabasa, kaya siguraduhin na
ipost ang inyong sagot sa mga puna sa ibaba.
function drawOscilloscope() { requestAnimationFrame(drawOscilloscope); const scopeCanvas = document.getElementById('oscilloscope'); const scopeContext = scopeCanvas.getContext('2d'); scopeCanvas.width = waveform.length; scopeCanvas.height = 200; scopeContext.clearRect(0, 0, scopeCanvas.width, scopeCanvas.height); scopeContext.beginPath(); for(let i = 0; i < waveform.length; i++) { const x = i; const y = ( 0.5 + (waveform[i] / 2) ) * scopeCanvas.height; if(i == 0) { scopeContext.moveTo(x, y); } else { scopeContext.lineTo(x, y); } } scopeContext.stroke(); }
Ito ang kabuuang gawain na nagawa natin
para maiguhit ang wave form na tatawagan natin pagkatapos ng song.play()
na
nilagay sa loob ng audioSetup
na gawain, na nagsasama rin ng updateWaveForm
na gawain.
Pangwakas na mga Isipin
Ipinaliwanag ko lamang yung mga importante sa demo, pero siguraduhing basahin niyo ang mga ibang bahagi ng demo para maitindihan kung paano ang mga pindutan sa radyo at kung paano gumagana ang simulang pindutan kaugnay ng kowd sa itaas, kasama ang estilong CSS.
Ang Web Audio API ay kakagiliwan ng marami na intersado sa anumang uri ng audio, at sana lalo nyo laliman. Nangolekta ako ng mga nakakatuwang halimbawa mula sa CodePen na gumagamit ng Web Audio API para gumawa ng ilang nakakagiliw na mga halimbawa. Magpakasaya!
- https://codepen.io/collection/XLYyWN
- https://codepen.io/collection/nNqdoR
- https://codepen.io/collection/XkNgkE
- https://codepen.io/collection/ArxwaW