Web Audio API ã®æãè峿·±ãæ©è½ã® 1 ã¤ã¯ããªã¼ãã£ãªã½ã¼ã¹ãã卿³¢æ°ã波形ããã®ä»ã®ãã¼ã¿ãæ½åºããããã使ç¨ãã¦ãã¸ã¥ã¢ã©ã¤ã¼ã¼ã·ã§ã³ã使ããæ©è½ã§ãããã®è¨äºã§ã¯ãæ¹æ³ã«ã¤ãã¦èª¬æããããã¤ãã®åºæ¬çãªä½¿ç¨ä¾ã示ãã¾ãã
ã¡ã¢: ãã¹ã¦ã®ã³ã¼ãã¹ããããã®å®éã®ä¾ã¯ãVoice-change-O-matic ã®ãã¢ã§ã覧ããã ãã¾ãã
åºæ¬çãªæ¦å¿µãªã¼ãã£ãªã½ã¼ã¹ãããã¼ã¿ãæ½åºããã«ã¯ AudioContext.createAnalyser()
ã¡ã½ããã使ç¨ãã¦ä½æããã AnalyserNode
ãå¿
è¦ã§ãã ä¾:
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioCtx.createAnalyser();
ãã®ãã¼ãã¯ãã½ã¼ã¹ã¨ destination ã®éã®ããæç¹ã§ãªã¼ãã£ãªã½ã¼ã¹ã«æ¥ç¶ããã¾ããä¾:
source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.connect(distortion);
distortion.connect(audioCtx.destination);
ã¡ã¢: å ¥åãã½ã¼ã¹ã«å¯¾ããç´æ¥ã¾ãã¯å¥ã®ãã¼ããä»ãã¦æ¥ç¶ããã¦ããããããã¢ãã©ã¤ã¶ã®åºåãå¥ã®ãã¼ãã«æ¥ç¶ããå¿ è¦ã¯ããã¾ããã
ã¢ãã©ã¤ã¶ãã¼ãã¯ãAnalyserNode.fftSize
ããããã£å¤ï¼æå®ããã¦ããªãå ´åã¯ãããã©ã«ã㯠2048 ã§ãï¼ã¨ãã¦æå®ããå
容ã«å¿ãã¦ãç¹å®ã®å¨æ³¢æ°ãã¡ã¤ã³ã§é«éãã¼ãªã¨å¤æï¼fftï¼ã使ç¨ãã¦ãªã¼ãã£ãªãã¼ã¿ããã£ããã£ãã¾ãã
ã¡ã¢: AnalyserNode.minDecibels
ã¨AnalyserNode.maxDecibels
ã使ç¨ãã¦ãfft ãã¼ã¿ã¹ã±ã¼ãªã³ã°ç¯å²ã®æå°å¤ã¨æå¤§å¤ãæå®ãããã¨ãã§ãã¾ããAnalyserNode.smoothingTimeConstant
ããããã®ä½¿ãæ¹ã®è©³ç´°ã«ã¤ãã¦ã¯ããããã®ãã¼ã¸ããèªã¿ãã ããã
ãã¼ã¿ãåå¾ããã«ã¯ã卿³¢æ°ãã¼ã¿ãåå¾ããããã«AnalyserNode.getFloatFrequencyData()
ããã³AnalyserNode.getByteFrequencyData()
ã¡ã½ããã使ç¨ããå¿
è¦ãããã¾ããAnalyserNode.getByteTimeDomainData()
㨠AnalyserNode.getFloatTimeDomainData()
ã使ç¨ãã¦æ³¢å½¢ãã¼ã¿ãåå¾ãã¾ãã
ãããã®ã¡ã½ããã¯ãã¼ã¿ãæå®ãããé
åã«ã³ãã¼ããã®ã§ããã¼ã¿ãåãåãåã«æ°ããé
åã使ãã¦å¼ã³åºãå¿
è¦ãããã¾ããæåã®ãã®ã¯ 32 ãããã®æµ®åå°æ°ç¹æ°ãçæãã2 çªç®ã¨ 3 çªç®ã®ãã®ã¯ 8 ãããã®ç¬¦å·ãªãæ´æ°ãçæãããããæ¨æºã® JavaScript é
åã§ã¯ãªããæ±ããã¼ã¿ã«å¿ãã¦Float32Array
ã¾ã㯠Uint8Array
é
åã使ãå¿
è¦ãããã¾ãã
ãã¨ãã°ã2048 ã® fft ãµã¤ãºãæ±ã£ã¦ããã¨ãã¾ããfft ã®ååã§ããAnalyserNode.frequencyBinCount
ã®å¤ãè¿ããfrequencyBinCount ã弿°ã¨ã㦠Uint8Array()ãå¼ã³åºãã¾ããããããã® fft ãµã¤ãºã§åéãããã¼ã¿ãã¤ã³ãã®æ°ã§ãã
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
å®éã«ãã¼ã¿ãåå¾ãã¦é åã«ã³ãã¼ããã«ã¯ãé åã弿°ã¨ãã¦æ¸¡ãã¦ãå¿ è¦ãªãã¼ã¿åéã¡ã½ãããå¼ã³åºãã¾ãã ä¾:
analyser.getByteTimeDomainData(dataArray);
ãªã¼ãã£ãªãã¼ã¿ãé
åã«åãè¾¼ãã æç¹ã§å¯è¦åãããã¨ãã§ãã¾ãããã¨ãã°ãHTML5 <canvas>
ã«ãããããããã¨ãã§ãã¾ãã
ããã¤ãã®å ·ä½ä¾ãè¦ã¦ã¿ã¾ãããã
波形/ãªã·ãã¹ã³ã¼ãã®ä½æãªã·ãã¹ã³ã¼ãã®ãã¸ã¥ã¢ã©ã¤ã¼ã¼ã·ã§ã³ï¼ Voice-change-O-matic ã®å ã®ã³ã¼ãã® Soledad Penadés ã«æè¬ãã¾ãï¼ã使ããã«ã¯ãåã®ã»ã¯ã·ã§ã³ã§èª¬æããæ¨æºãã¿ã¼ã³ã«å¾ã£ã¦ããããã¡ãè¨å®ãã¾ãã
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
次ã«ãæ°ãããã¸ã¥ã¢ã©ã¤ã¼ã¼ã·ã§ã³ãã£ã¹ãã¬ã¤ã®æºåãããããã«ãå ã«æç»ããããã£ã³ãã¹ãã¯ãªã¢ãã¾ãã
canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
ããã§ draw()
颿°ãå®ç¾©ãã¾ãã
ããã§ requestAnimationFrame()
ã使ç¨ãã¦ãæç»é¢æ°ãéå§å¾ã«ã«ã¼ããç¶æãã¾ãã
var drawVisual = requestAnimationFrame(draw);
次ã«ãTimeDomainData ãåå¾ããé åã«ã³ãã¼ãã¾ãã
analyser.getByteTimeDomainData(dataArray);
次ã«ãåæå¤ã¨ãã¦ãã£ã³ãã¹ãåè²ã§å¡ãã¤ã¶ãã¾ãã
canvasCtx.fillStyle = "rgb(200, 200, 200)";
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
æç»ããæ³¢ã®ç·å¹ ã¨ç·ã®è²ãè¨å®ãããã¹ãæç»ãã¾ãã
canvasCtx.lineWidth = 2;
canvasCtx.strokeStyle = "rgb(0, 0, 0)";
canvasCtx.beginPath();
ãã£ã³ãã¹ã®å¹ ãé åã®é·ã(å ã»ã©å®ç¾©ãã frequencyBinCount ã¨çãã)ã§é¤ç®ãããã¨ã«ãã£ã¦æãããç·ã®åã»ã°ã¡ã³ãã®å¹ ãæ±ºå®ããæ¬¡ã«ã夿° x ãå®ç¾©ãã¦ããã¹ã®åã»ã°ã¡ã³ããæç»ããããã«ç§»åããä½ç½®ãå®ç¾©ãã¾ãã
var sliceWidth = (WIDTH * 1.0) / bufferLength;
var x = 0;
次ã«ã«ã¼ããå®è¡ãã¦ããããã¡å ã®åãã¤ã³ãã®æ³¢ã®å°ããªã»ã°ã¡ã³ãã®ä½ç½®ããé åããã®ãã¼ã¿ãã¤ã³ãå¤ã«åºã¥ãã¦ç¹å®ã®é«ãã«å®ç¾©ããç·ãæ¬¡ã®æ³¢ã»ã°ã¡ã³ããæç»ãããã¹ãå ´æã«ç§»åããã¾ãã
for (var i = 0; i < bufferLength; i++) {
var v = dataArray[i] / 128.0;
var y = (v * HEIGHT) / 2;
if (i === 0) {
canvasCtx.moveTo(x, y);
} else {
canvasCtx.lineTo(x, y);
}
x += sliceWidth;
}
æå¾ã«ããã£ã³ãã¹ã®å³ç«¯ã®éä¸ã§ç·ãçµããæ¬¡ã«å®ç¾©ããç·ãæç»ãã¾ãã
canvasCtx.lineTo(canvas.width, canvas.height/2);
canvasCtx.stroke();
};
ãã®ã³ã¼ãã®æå¾ã§ã¯ã draw()
颿°ãå¼ã³åºãã¦ããã»ã¹å
¨ä½ãéå§ãã¾ãã
ããã«ããã1 ç§ã«æ°åæ´æ°ããç´ æ´ãããæ³¢å½¢è¡¨ç¤ºãå¾ããã¾ãã
卿³¢æ°æ£ã°ã©ãã®ä½ææ¬¡ã«ä½æããç´ æµãªå°ããªãµã¦ã³ããã¸ã¥ã¢ã©ã¤ã¼ã¼ã·ã§ã³ã¯ãWinamp ã®ãããªå¨æ³¢æ°æ£ã°ã©ãã® 1 ã¤ã§ããç§ãã¡ã¯ Voice-change-O-matic ã§å ¥æã§ãããã®ãæã£ã¦ãã¾ãããããã©ã®ããã«è¡ãããããè¦ã¦ã¿ã¾ãããã
ã¾ããã¢ãã©ã¤ã¶ã¨ãã¼ã¿é
åãè¨å®ããclearRect()
ã§ç¾å¨ã®ãã£ã³ãã¹è¡¨ç¤ºãæ¶å»ãã¾ããããã¾ã§ã®å¯ä¸ã®éãã¯ãfft ãµã¤ãºããã£ã¨å°ãããããã¨ã§ããããã¯ãã°ã©ãã®åãã¼ãç´°ãä¸çã§ã¯ãªããã¼ã®ããã«è¦ããã»ã©å¤§ããããããã§ãã
analyser.fftSize = 256;
var bufferLength = analyser.frequencyBinCount;
console.log(bufferLength);
var dataArray = new Uint8Array(bufferLength);
canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
次ã«ãdraw()
颿°ããªãã«ããrequestAnimationFrame()
ã§ã«ã¼ããè¨å®ãã¦ã表示ããããã¼ã¿ãæ´æ°ãããããã«ãã¦ãããåã¢ãã¡ã¼ã·ã§ã³ãã¬ã¼ã ã§è¡¨ç¤ºãã¯ãªã¢ãã¾ãã
function draw() {
drawVisual = requestAnimationFrame(draw);
analyser.getByteFrequencyData(dataArray);
canvasCtx.fillStyle = 'rgb(0, 0, 0)';
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
ä»åº¦ã¯ãã¼ã®å¹ ããã£ã³ãã¹ã®å¹ ããã¼ã®æ°ã§å²ã£ãå¤ï¼ãããã¡ã®é·ãï¼ã«çãããªãããã«è¨å®ãã¾ãããããããã®å¹ ã 2.5 åã«ãã¦ãã¾ãããªããªããæ¯æ¥èãã¦ããé³ã®å¤§é¨åãç¹å®ã®ä½ã卿³¢æ°å¸¯ã«ããã®ã§ãã»ã¨ãã©ã®å¨æ³¢æ°ããã®ä¸ã«ãªã¼ãã£ãªãæããªããã®ã¨ãã¦æ»ã£ã¦ããããã§ããç©ºã®æ£ã°ã©ãã表示ããããªãã®ã§ãæ£ã®ä½ç½®ããããã¦ãæå³ã®ããé«ããæã¤ãã®ã§ãã£ã³ãã¹ã®è¡¨ç¤ºãåãã¾ãã
ããã¦ã夿° barHeight
ã¨ãç¾å¨ã®ãã¼ãæç»ããç»é¢ä¸ã®æ¨ªä½ç½®ãè¨é²ãã夿° x
ãè¨å®ãã¾ãã
var barWidth = (WIDTH / bufferLength) * 2.5;
var barHeight;
var x = 0;
åã¨åãããã«ãfor ã«ã¼ããéå§ããdataArray
ã®åå¤ã«ã¤ãã¦ç¹°ãè¿ãã¾ããããããã®å¤ã«ã¤ãã¦ãbarHeight
ãé
åã®å¤ã«è¨å®ããbarHeight
ã«åºã¥ãã¦å¡ãã¤ã¶ãã®è²ãè¨å®ãï¼é«ãã®ãã¼ã¯æãããªãã¾ãï¼ãbarWidth
ã®å¹
ããã³ barHeight/2
ã®é«ããæã¤æ£ãããã£ã³ãã¹ã®æ°´å¹³æ¹å x
ãã¯ã»ã«ã®ä½ç½®ã«æç»ãã¾ãï¼æã
ã¯æçµçã«åãã¼ãååã«ã«ãããããã¨ã«ããã®ã§ããã£ã³ãã¹ã«ãã¹ã¦åã¾ãããã«ãªãã¾ããï¼ã
åãã¼ãæç»ããåç´ãªãã»ããä½ç½®ã«ã¤ãã¦ã¯èª¬æãå¿
è¦ã§ããããHEIGHT-barHeight/2
ã§ããç§ã¯ãåç´ä½ç½®ã 0 ã«è¨å®ããå ´åã®ããã«åãã¼ãä¸ããä¸ã«è¡¨ç¤ºãããã®ã§ã¯ãªãããã£ã³ãã¹ã®ä¸ããåºãããã«ãããããããããå®è¡ãã¦ãã¾ãããã®ãããæ¯ååç´ä½ç½®ã«ããã£ã³ãã¹ã®é«ããã barHeight/2
ãå¼ãããã®ãã»ãããã¦ãã¾ãããããã£ã¦ãåãã¼ã¯ããã£ã³ãã¹ã®éä¸ããä¸ã¾ã§æç»ããã¾ãã
for(var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i]/2;
canvasCtx.fillStyle = 'rgb(' + (barHeight+100) + ',50,50)';
canvasCtx.fillRect(x,HEIGHT-barHeight/2,barWidth,barHeight);
x += barWidth + 1;
}
};
ããã§ããã³ã¼ãã®æå¾ã« draw()
颿°ãå¼ã³åºãã¦ãããã»ã¹å
¨ä½ãåããããã«è¨å®ãã¾ãã
ãã®ã³ã¼ãã§ã¯ã次ã®ãããªçµæãå¾ããã¾ãã
ã¡ã¢: ãã®è¨äºã«è¨è¼ããã¦ããä¾ã§ã¯ãAnalyserNode.getByteFrequencyData()
ã¨AnalyserNode.getByteTimeDomainData()
ã§ä½¿ç¨æ³ã示ããã¦ãã¾ããå®éã®ä¾ã¯AnalyserNode.getFloatFrequencyData()
ã¨AnalyserNode.getFloatTimeDomainData()
ã«ããã®ã§ãç§ãã¡ã® Voice-change-O-matic-float-data ãã¢ãåç
§ãã¦ãã ããï¼ã½ã¼ã¹ã³ã¼ããåç
§ãã¦ãã ããï¼â ããã¯ãå
ã® Voice-change-O-matic ã¨ã¾ã£ããåãã§ããã符å·ãªããã¤ããã¼ã¿ã§ã¯ãªããFloat ãã¼ã¿ã使ç¨ãã¦ãã¾ãã
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4