å·²å¼ç¨: ä¸åæ¨è使ç¨è¯¥ç¹æ§ãè½ç¶ä¸äºæµè§å¨ä»ç¶æ¯æå®ï¼ä½ä¹è®¸å·²ä»ç¸å ³ç web æ åä¸ç§»é¤ï¼ä¹è®¸æ£åå¤ç§»é¤æåºäºå ¼å®¹æ§èä¿çã请尽éä¸è¦ä½¿ç¨è¯¥ç¹æ§ï¼å¹¶æ´æ°ç°æç代ç ï¼åè§æ¬é¡µé¢åºé¨çå ¼å®¹æ§è¡¨æ ¼ä»¥æå¯¼ä½ ä½åºå³å®ã请注æï¼è¯¥ç¹æ§éæ¶å¯è½æ æ³æ£å¸¸å·¥ä½ã
AudioContext
æ¥å£ç createScriptProcessor()
æ¹æ³å建ä¸ä¸ª ScriptProcessorNode
ï¼ç¨äºç´æ¥ä½¿ç¨ JavaScript å¤çé³é¢ã
夿³¨ï¼ æ¤ç¹æ§å·²è¢« AudioWorklet å AudioWorkletNode
æ¥å£æ¿ä»£ã
createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels)
åæ°
bufferSize
ä»¥éæ ·å¸§ä¸ºåä½çç¼å²åºå¤§å°ãå ·ä½æ¥è®²ï¼ç¼å²åºå¤§å°å¿ é¡»æ¯ä¸é¢è¿äºå¼å½ä¸çæä¸ä¸ªï¼256ã512ã1024ã2048ã4096ã8192ã16384ãå¦ææªæä¾åæ°ï¼æè åæ°ä¸º 0ï¼ååå½åç¯å¢æåéçç¼å²åºå¤§å°ï¼åå¼ä¸º 2 ç广¬¡æ¹çä¸ä¸ªå¸¸æ°ï¼å ¶å¨è¯¥ç»ç¹çæ´ä¸ªçå½å¨æä¸é½ä¸åï¼ã
该å弿§å¶ç audioprocess
äºä»¶è¢«åæ´¾çé¢çï¼ä»¥åæ¯ä¸æ¬¡è°ç¨å¤å°éæ ·å¸§è¢«å¤çãæ´å°ç bufferSize
æå³çæ´ä½çå»¶è¿ãèæ´å¤§çå¼åå¯ä»¥é¿å
é³é¢ç䏿åæ
éãæ¨èä¸è¦ç»å®å
·ä½çç¼å²åºå¤§å°ï¼è®©ç³»ç»èªå·±éä¸ä¸ªå¥½ç弿¥å¹³è¡¡å»¶è¿åé³é¢è´¨éã
numberOfInputChannels
æ´æ°ï¼ç¨äºæå®è¾å ¥ç»ç¹ç声éçæ°éï¼é»è®¤å¼ä¸º 2 䏿é«å¯å 32ã
numberOfOutputChannels
æ´æ°ï¼ç¨äºæå®è¾åºç»ç¹ç声éçæ°éï¼é»è®¤å¼ä¸º 2 䏿é«å¯å 32ã
è¦åï¼ Webkitï¼çæ¬ 31ï¼è¦æ±è°ç¨è¿ä¸ªæ¹æ³çæ¶åå¿
é¡»ä¼ å
¥ä¸ä¸ªææç bufferSize
ã
夿³¨ï¼ åæ¶å° numberOfInputChannels
ãnumberOfOutputChannels
è®¾ç½®ä¸ºé¶æ¯æ æçã
ä¸é¢ç示ä¾å±ç¤ºäºå¦ä½ä½¿ç¨ ScriptProcessorNode
è·åéè¿ AudioContext.decodeAudioData()
å è½½çé³è½¨å¹¶å¯¹å
¶è¿è¡å¤çï¼ä¸ºè¾å
¥é³è½¨çæ¯ä¸ªé³é¢æ ·æ¬æ·»å ä¸ç¹ç½åªå£°ï¼ç¶åéè¿ AudioDestinationNode
è¿è¡ææ¾ã
å¯¹äºæ¯ä¸ªééåæ¯ä¸ªéæ ·å¸§ï¼èæ¬èç¹ç audioprocess
äºä»¶å¤çå¨é½ä¼ä½¿ç¨ç¸å
³ç audioProcessingEvent
æ¥å¾ªç¯å¤çè¾å
¥ç¼å²åºçæ¯ä¸ªééåæ¯ä¸ªééä¸çæ¯ä¸ªæ ·æ¬ï¼å¹¶æ·»å å°éç½åªå£°ï¼ç¶åå°ç»æè®¾ç½®ä¸ºæ¯ç§æ
åµä¸çè¾åºæ ·æ¬ã
夿³¨ï¼ ä½ å¯ä»¥å¨çº¿è¿è¡å®æ´ç示ä¾ï¼ææ¥çæºä»£ç ã
const myScript = document.querySelector("script");
const myPre = document.querySelector("pre");
const playButton = document.querySelector("button");
// å建 AudioContext ä¸ç¼å²æº
let audioCtx;
async function init() {
audioCtx = new AudioContext();
const source = audioCtx.createBufferSource();
// å建ä¸ä¸ªç¼å²åºå¤§å°ï¼bufferSizeï¼ä¸º 4096ã
// åä¸è¾å
¥åè¾åºééç ScriptProcessorNode
const scriptNode = audioCtx.createScriptProcessor(4096, 1, 1);
// ä½¿ç¨ fetch() å decodeAudioData() æ¥å è½½é³è½¨
try {
const response = await fetch("viper.ogg");
const arrayBuffer = await response.arrayBuffer();
source.buffer = await audioCtx.decodeAudioData(arrayBuffer);
} catch (err) {
console.error(
`Unable to fetch the audio file: ${name} Error: ${err.message}`,
);
}
// åç»ç¹æ·»å ä¸ä¸ªç¨äºå¤çé³é¢äºä»¶ç彿°
scriptNode.addEventListener("audioprocess", (audioProcessingEvent) => {
// è¿éçè¾å
¥ç¼å²åºå³ä¸ºæä»¬å颿å è½½çææ²
let inputBuffer = audioProcessingEvent.inputBuffer;
// è¾åºç¼å²åºåä¼å
å«å°è¦è¢«ä¿®æ¹ãææ¾çéæ ·
let outputBuffer = audioProcessingEvent.outputBuffer;
// å¨è¾åºééé´å¾ªç¯ï¼å¨æ¬ä¾ä¸ï¼è¾åºééä»
æä¸ä¸ªï¼
for (let channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
let inputData = inputBuffer.getChannelData(channel);
let outputData = outputBuffer.getChannelData(channel);
// 循ç¯è¿ä»£ 4096 ç»éæ ·
for (let sample = 0; sample < inputBuffer.length; sample++) {
// 让è¾åºçåäºè¾å
¥
outputData[sample] = inputData[sample];
// ååå
¶ä¸å ä¸äºåªé³
outputData[sample] += (Math.random() * 2 - 1) * 0.1;
}
}
});
source.connect(scriptNode);
scriptNode.connect(audioCtx.destination);
source.start();
// å½ç¼å²æºåæ¢ææ¾çæ¶åï¼æå¼ä¸åçè¿æ¥
source.addEventListener("ended", () => {
source.disconnect(scriptNode);
scriptNode.disconnect(audioCtx.destination);
});
}
// è¿æ¥ææ¾æé®
playButton.addEventListener("click", () => {
if (!audioCtx) {
init();
}
});
è§è æµè§å¨å
¼å®¹æ§ åè§
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