Baseline Widely available *
Web Audio API æä¾äºå¨ Web 䏿§å¶é³é¢çä¸ä¸ªé常ææéç¨çç³»ç»ï¼å 许å¼åè æ¥èªéé³é¢æºï¼å¯¹é³é¢æ·»å ç¹æï¼ä½¿é³é¢å¯è§åï¼æ·»å ç©ºé´ææï¼å¦å¹³ç§»ï¼ï¼ççã
Web audio æ¦å¿µä¸ä½¿ç¨Web Audio API ä½¿ç¨æ·å¯ä»¥å¨é³é¢ä¸ä¸æï¼AudioContextï¼ä¸è¿è¡é³é¢æä½ï¼å ·ææ¨¡ååè·¯ç±çç¹ç¹ãå¨é³é¢èç¹ä¸æä½è¿è¡åºç¡çé³é¢ï¼å®ä»¬è¿æ¥å¨ä¸èµ·ææé³é¢è·¯ç±å¾ãå³ä½¿å¨å个ä¸ä¸æä¸ä¹æ¯æå¤æºï¼å°½ç®¡è¿äºé³é¢æºå ·æå¤ç§ä¸åç±»åééå¸å±ãè¿ç§æ¨¡åå设计æä¾äºçµæ´»åå»ºå¨æææçå¤åé³é¢çæ¹æ³ã
é³é¢èç¹éè¿å®ä»¬çè¾å
¥è¾åºç¸äºè¿æ¥ï¼å½¢æä¸ä¸ªé¾æè
ä¸ä¸ªç®åçç½ãä¸è¬æ¥è¯´ï¼è¿ä¸ªé¾æç½èµ·å§äºä¸ä¸ªæå¤ä¸ªé³é¢æºãé³é¢æºå¯ä»¥æä¾ä¸ä¸ªç段ä¸ä¸ªç段çé³é¢éæ ·æ°æ®ï¼ä»¥æ°ç»çæ¹å¼ï¼ï¼ä¸è¬ï¼ä¸ç§éçé³é¢æ°æ®å¯ä»¥è¢«ååæå ä¸ä¸ªè¿æ ·ççæ®µãè¿äºç段å¯ä»¥æ¯ç»è¿ä¸äºæ°å¦è¿ç®å¾å°ï¼æ¯å¦OscillatorNode
ï¼ï¼ä¹å¯ä»¥æ¯é³é¢æè§é¢çæä»¶è¯»åºæ¥çï¼æ¯å¦AudioBufferSourceNode
åMediaElementAudioSourceNode
ï¼ï¼åæè
æ¯é³é¢æµï¼MediaStreamAudioSourceNode
ï¼ãå
¶å®ï¼é³é¢æä»¶æ¬èº«å°±æ¯å£°é³çéæ ·æ°æ®ï¼è¿äºéæ ·æ°æ®å¯ä»¥æ¥èªéº¦å
é£ï¼ä¹å¯ä»¥æ¥èªçµåä¹å¨ï¼ç¶åæ··åæä¸ä¸ªåä¸çå¤æçæ³¢å½¢ã
è¿äºèç¹çè¾åºå¯ä»¥è¿æ¥å°å
¶ä»èç¹çè¾å
¥ä¸ï¼ç¶åæ°èç¹å¯ä»¥å¯¹æ¥æ¶å°çéæ ·æ°æ®åè¿è¡å
¶ä»çå¤çï¼åå½¢æä¸ä¸ªç»ææµãä¸ä¸ªæå¸¸è§çæä½æ¯éè¿æè¾å
¥çéæ ·æ°æ®æ¾å¤§æ¥è¾¾å°æ©é³å¨çä½ç¨ï¼ç¼©å°å°±æ¯ä¸ä¸ªå¼±é³å¨ï¼ï¼åè§GainNode
ï¼ã声é³å¤ç宿ä¹åï¼å¯ä»¥è¿æ¥å°ä¸ä¸ªç®çå°ï¼AudioContext.destination
ï¼ï¼è¿ä¸ªç®çå°è´è´£æå£°é³æ°æ®ä¼ è¾ç»æ¬å£°å¨æè
è³æºã注æï¼åªæå½ç¨æ·ææå¬å°å£°é³æ¶ï¼æéè¦è¿è¡æåä¸ä¸ªè¿ä¸ªè¿æ¥ã
ä¸ä¸ªç®åèå ¸åç web audio æµç¨å¦ä¸ï¼
<audio>
, æ¯è¡å¨ï¼æµä½¿ç¨è¿ä¸ª APIï¼æ¶é´å¯ä»¥è¢«éå¸¸ç²¾ç¡®å°æ§å¶ï¼å 乿²¡æå»¶è¿ï¼è¿æ ·å¼å人åå¯ä»¥åç¡®å°ååºäºä»¶ï¼å¹¶ä¸å¯ä»¥éå¯¹éæ ·æ°æ®è¿è¡ç¼ç¨ï¼çè³æ¯è¾é«çéæ ·çãè¿æ ·ï¼é¼ç¹åèææ¯åç¡®æ 误çã
Web Audio API ä¹ä½¿æä»¬è½å¤æ§å¶é³é¢ç空é´åãå¨åºäºæº - 侦å¬å¨æ¨¡åçç³»ç»ä¸ï¼å®å 许æ§å¶å¹³ç§»æ¨¡ååå¤çè·ç¦»å¼èµ·çè¡°åæç§»å¨æºï¼ç§»å¨ä¾¦å¬ï¼å¼èµ·ç夿®åæåºã
夿³¨ï¼ ä½ å¯ä»¥é 读æä»¬å ³äº Web Audio API çæç« æ¥äºè§£æ´å¤ç»è Web Audio API èåçåºæ¬æ¦å¿µã
Web Audio API æ¥å£Web Audio API å ±æä¸ç³»åæ¥å£åç¸å ³çäºä»¶ï¼æä»¬å·²ç»æå®ä»¬åæäºä¹ç±»åè½ã
éç¨é³é¢å¾å®ä¹Web Audio API ä¸ä¸çæé³é¢å¾ç¸å ³çå®ä¹ä¸éç¨å®¹å¨ã
AudioContext
AudioContext
æ¥å£ä»£è¡¨ç±é³é¢æ¨¡åææçé³é¢å¤çå¾ãé³é¢ä¸ä¸ææ§å¶å
¶æå
å«èç¹çå建åé³é¢å¤çãè§£ç ã使ç¨å
¶ä»æ¥å£åä½ å¿
éå建ä¸ä¸ªé³é¢ä¸ä¸æ
ï¼ä¸åæä½é½å¨è¿ä¸ªç¯å¢éè¿è¡ã
AudioNode
é³é¢èç¹
æ¥å£æ¯ä¸ä¸ªé³é¢å¤ç模åï¼ä¾å¦é³é¢æºï¼<audio>
æ<video>
ï¼ï¼é³é¢è¾åºãä¸é´å¤ç模åï¼ä¾å¦ï¼æ»¤æ³¢å¨ BiquadFilterNode
æè
é³éæ§å¶å¨ GainNode
ï¼ã
AudioParam
AudioParam
æ¥å£ä»£è¡¨é³é¢ç¸å
³çåæ°ï¼æ¯å¦ä¸ä¸ª AudioNode
çåæ°ãå®å¯ä»¥è®¾ç½®ä¸ºç¹å®å¼æå¼çååï¼å¹¶ä¸å¯ä»¥å¨æå®çæ¶é´ä¹å以æå®æ¨¡å¼åæ´ã
ended
ç»æäºä»¶
å½åªä½ææ¾åæ¢æ¶ï¼ä¼è§¦åended
äºä»¶ã
Web Audio API 使ç¨çé³é¢æºæ¥å£ã
OscillatorNode
OscillatorNode
æ¥å£ä»£è¡¨ä¸ç§éæ¶é´ååçæ³¢å½¢ï¼æ¯å¦æ£å¼¦æ³¢å½¢æä¸è§æ³¢å½¢ãç±»åæ¯AudioNode
ï¼åè½æ¯é³é¢å¤ç模åï¼å¯ä»¥äº§çæå®é¢ççæ³¢å½¢ã
AudioBuffer
AudioBuffer
代表å
åä¸ç䏿®µé³é¢æ°æ®ï¼å¯ä»¥éè¿AudioContext.decodeAudioData()
æ¹æ³ä»é³é¢æä»¶å建ï¼ä¹å¯ä»¥éè¿AudioContext.createBuffer()
æ¹æ³ä»åå§æ°æ®å建ãå½é³é¢æ°æ®è¢«è§£ç æè¿ç§æ ¼å¼ä¹åï¼å°±å¯ä»¥è¢«æ¾å
¥ä¸ä¸ªAudioBufferSourceNode
ä¸ä½¿ç¨ã
AudioBufferSourceNode
AudioBufferSourceNode
表示ç±å
åé³é¢æ°æ®ç»æçé³é¢æºï¼é³é¢æ°æ®åå¨å¨AudioBuffer
ä¸ãè¿æ¯ä¸ä¸ªä½ä¸ºé³é¢æºçAudioNode
ã
MediaElementAudioSourceNode
MediaElementAudioSourceNode
æ¥å£è¡¨ç¤ºç± HTML5 <audio>
æ<video>
å
ç´ çæçé³é¢æºãè¿æ¯ä¸ä¸ªä½ä¸ºé³é¢æºçAudioNode
ã
MediaStreamAudioSourceNode
MediaStreamAudioSourceNode
æ¥å£è¡¨ç¤ºç± WebRTC MediaStream
ï¼å¦ç½ç»æå头æéº¦å
é£ï¼çæçé³é¢æºãè¿æ¯ä¸ä¸ªä½ä¸ºé³é¢æºçAudioNode
ã
åºç¨å°é³é¢æºä¸ç鳿ã
BiquadFilterNode
BiquadFilterNode
æ¥å£è¡¨ç¤ºä¸ä¸ªç®åçä½é¶æ»¤æ³¢å¨ã宿¯ä¸ä¸ªAudioNode
ï¼å¯ä»¥è¡¨ç¤ºä¸åç§ç±»ç滤波å¨ãè°é³å¨æå¾å½¢åè¡¡å¨ãBiquadFilterNode
æ»æ¯åªæä¸ä¸ªè¾å
¥åä¸ä¸ªè¾åºã
ConvolverNode
ConvolverNode
æ¥å£æ¯ä¸ä¸ªAudioNode
ï¼å¯¹ç»å®ç AudioBuffer æ§è¡çº¿æ§å·ç§¯ï¼é常ç¨äºå®ç°æ··åææã
DelayNode
DelayNode
æ¥å£è¡¨ç¤ºå»¶è¿çº¿ï¼æ¯AudioNode
ç±»åçé³é¢å¤ç模åï¼ä½¿è¾å
¥çæ°æ®å»¶æ¶è¾åºã
DynamicsCompressorNode
DynamicsCompressorNode
æä¾äºä¸ä¸ªå缩ææï¼å½å¤ä¸ªé³é¢å¨åæ¶ææ¾å¹¶ä¸æ··åçæ¶åï¼å¯ä»¥éè¿å®éä½é³éæå¤§çé¨åçé³éæ¥å¸®å©é¿å
åçåæ³¢å失çã
GainNode
GainNode
æ¥å£ç¨äºé³éååã宿¯ä¸ä¸ª AudioNode
ç±»åçé³é¢å¤ç模åï¼è¾å
¥ååºç¨å¢ç ææï¼ç¶åè¾åºã
StereoPannerNode
StereoPannerNode
æ¥å£è¡¨ç¤ºä¸ä¸ªç®åç«ä½å£°æ§å¶èç¹ï¼ç¨æ¥å·¦å³ç§»å¨é³é¢æµã
WaveShaperNode
WaveShaperNode
æ¥å£è¡¨ç¤ºä¸ä¸ªé线æ§çææ²ã宿¯AudioNode
ç±»åï¼å¯ä»¥å©ç¨æ²çº¿æ¥å¯¹ä¿¡å·è¿è¡ææ²ãé¤äºä¸äºææææ¾çææ²ï¼è¿å¸¸è¢«ç¨æ¥ç»å£°é³æ·»å 温æçæè§ã
PeriodicWave
ç¨æ¥å®ä¹å¨ææ§ç波形ï¼å¯è¢«ç¨æ¥éå¡ OscillatorNode
çè¾åºã
å¨ä½ å¤çå®é³é¢ä¹åï¼è¿äºæ¥å£å®ä¹äºè¾åºå°åªéã
AudioDestinationNode
AudioDestinationNode
å®ä¹äºæåé³é¢è¦è¾åºå°åªéï¼é常æ¯è¾åºå°ä½ çæ¬å£°å¨ã
MediaStreamAudioDestinationNode
MediaStreamAudioDestinationNode
å®ä¹äºä½¿ç¨ WebRTC çMediaStream
ï¼åªå
å«å个 AudioMediaStreamTrackï¼åºè¯¥è¿æ¥çç®çå°ï¼AudioMediaStreamTrack çä½¿ç¨æ¹å¼åä»getUserMedia()
ä¸å¾å°MediaStream
ç¸ä¼¼ãè¿ä¸ªæ¥å£æ¯AudioNode
ç±»åçé³é¢ç®çå°ã
å¦æä½ æ³ä»é³é¢éæåæ¶é´ãé¢çæè å ¶ä»æ°æ®ï¼ä½ éè¦ AnalyserNodeã
AnalyserNode
AnalyserNode
表示ä¸ä¸ªå¯ä»¥æä¾å®æ¶é¢çåæä¸æ¶ååæçåç¹ï¼è¿äºåææ°æ®å¯ä»¥ç¨åæ°æ®åæåå¯è§åã
ä½ å°ä½¿ç¨è¿äºæ¥å£æ¥æåãå并声éã
ChannelSplitterNode
ChannelSplitterNode
å¯ä»¥æè¾å
¥æµçæ¯ä¸ªå£°éè¾åºå°ä¸ä¸ªç¬ç«çè¾åºæµã
ChannelMergerNode
ChannelMergerNode
ç¨äºæä¸ç»è¾å
¥æµåæå°ä¸ä¸ªè¾åºæµãè¾åºæµçæ¯ä¸ä¸ªå£°é对åºä¸ä¸ªè¾å
¥æµã
è¿äºæ¥å£ç¨æ¥æ·»å 空é´å¹³ç§»ææå°é³é¢æºã
AudioListener
**AudioListener
**ä»£è¡¨åºæ¯ä¸æ£å¨å¬å£°é³ç人çä½ç½®åæåã
PannerNode
PannerNode
ç¨äºè¡¨ç¤ºåºæ¯æ¯å£°é³ç空é´è¡ä¸ºã宿¯AudioNode
ç±»åçé³é¢å¤ç模åï¼è¿ä¸ªèç¹ç¨äºè¡¨ç¤ºå³æç¬å¡å°åæ ç³»é声æºçä½ç½®ä¿¡æ¯ï¼è¿å¨ä¿¡æ¯ï¼éè¿ä¸ä¸ªé度åé表示ï¼ï¼æ¹åä¿¡æ¯ï¼éè¿ä¸ä¸ªæ¹ååé¥è¡¨ç¤ºï¼ã
å¯ä»¥ç¼å JavaScript ä»£ç æ¥å¤çé³é¢æ°æ®ãå½ç¶ï¼è¿éè¦ç¨å°ä¸é¢çæ¥å£åäºä»¶ã
夿³¨ï¼ è¿äºåè½å¨ Web Audio API ç 2014 å¹´ 8 æ 9 æ¥çæ¬ä¸å·²ç»æ è®°ä¸ºä¸æ¨èçï¼è¿äºåè½å¾å¿«ä¼è¢«Audio_Workers代æ¿ã
ScriptProcessorNode
ScriptProcessorNode
æ¥å£ç¨äºéè¿ JavaScript 代ç çæï¼å¤çï¼åæé³é¢ã宿¯ä¸ä¸ªAudioNode
ç±»åçé³é¢å¤ç模åï¼ä½æ¯å®ä¸ä¸¤ä¸ªç¼å²åºç¸è¿æ¥ï¼ä¸ä¸ªç¼å²åºéå
å«å½åçè¾å
¥æ°æ®ï¼å¦ä¸ä¸ªç¼å²åºéå
å«çè¾åºæ°æ®ãæ¯å½æ°çé³é¢æ°æ®è¢«æ¾å
¥è¾å
¥ç¼å²åºï¼å°±ä¼äº§çä¸ä¸ªAudioProcessingEvent
äºä»¶ï¼å½è¿ä¸ªäºä»¶å¤çç»ææ¶ï¼è¾åºç¼å²åºéåºè¯¥åå¥½äºæ°æ°æ®ã
audioprocess
(event)
å½ä¸ä¸ª Web Audio API ScriptProcessorNode
å·²ç»åå¤å¥½è¿è¡å¤çæ¶ï¼è¿ä¸ªäºä»¶åè°ä¼è¢«è°ç¨ã
AudioProcessingEvent
å½ScriptProcessorNode
çè¾å
¥æµæ°æ®åå¤å¥½äºæ¶ï¼AudioProcessingEvent
äºä»¶ä¼äº§çã
å¨åå°è¿è¡é³é¢çå¿«éå¤ç乿¯å¯ä»¥çãä»
ä»
çæå
å«é³é¢æ°æ®çAudioBuffer
ï¼èä¸å¨æ¬å£°å¨éææ¾å®ã
OfflineAudioContext
OfflineAudioContext
离线é³é¢ä¸ä¸æä¹æ¯é³é¢ä¸ä¸æAudioContext
ï¼ä¹è¡¨ç¤ºæAudioNode
è¿æ¥å°ä¸èµ·çä¸ä¸ªé³é¢å¤çå¾ã使¯ï¼ä¸ä¸ä¸ªæ åçé³é¢ä¸ä¸æç¸æ¯ï¼ç¦»çº¿ä¸ä¸æä¸è½æé³é¢æ¸²æå°æ¬å£°å¨ï¼ä»
ä»
æ¯æé³é¢æ¸²æå°ä¸ä¸ªç¼å²åºã
complete
(event)
Complete äºä»¶ï¼å½ç¦»çº¿é³é¢ä¸ä¸æè¢«ç»æ¢æ¶äº§çã
OfflineAudioCompletionEvent
OfflineAudioCompletionEvent
表示ä¸ä¸æè¢«ç»æ¢æ¶çäºä»¶ã
å¨äºè§£è¿ä¸é¨åå
容ä¹åï¼ä½ å¯ä»¥å
äºè§£ä¸ä¸ªæ°ç WebWorker æ¹é¢çå
容ãé³é¢å·¥ä½è
æä¾äºä¸ç§å¯ä»¥å¨ä¸ä¸ªWebWorkerä¸ä¸æä¸ç´æ¥è¿è¡é³é¢å¤ççæ¹å¼ãç°å¨å·²ç»å®ä¹äºä¸äºè¿é¨ååè½çæ°æ¥å£ï¼æ¥å£å®ä¹æ¯å¨ 2014 å¹´ç 8 æ 29 æ¥ææ¡£ä¸ãå°ç®å为æ¢ï¼è¿æ²¡ææµè§å¨å·²ç»å¯¹è¿äºæ¥å£è¿è¡äºå®ç°ãå½è¿äºæ¥å£è¢«å®ç°åï¼ScriptProcessorNode
ååæä¸æå°çå
¶ä»æ¥å£é½ä¼è¢«æ¿ä»£ã
AudioWorkerNode
AudioWorkerNode 乿¯AudioNode
ç±»åï¼ä½æ¯å®ç¨äºä¸å·¥ä½è
线ç¨å使¥ç´æ¥å®æé³é¢ççæï¼å¤çæåæçæä½ã
AudioWorkerGlobalScope
AudioWorkerGlobalScope
ç»§æ¿äº DedicatedWorkerGlobalScope
ã代表ä¸ä¸ªå·¥ä½è
ä¸ä¸æãè¿ä¸ªå·¥ä½è
ä¸ä¸æéè¿è¡ç对é³é¢è¿è¡å¤ççèæ¬ã设计è¿ä¸ªæ¥å£çç®çï¼æ¯ä¸ºäºç´æ¥éè¿ç¼å JavaScript 代ç ï¼æ¥å®æå¯¹é³é¢æ°æ®ççæï¼å¤çï¼åæå·¥ä½ã
AudioProcessEvent
è¿æ¯ä¸ä¸ªäºä»¶å¯¹è±¡ãè¿ä¸ªå¯¹è±¡ä¼è¢«ååç»AudioWorkerGlobalScope
对象æ¥è¿è¡å¤çã
ä¸é¢ä»ç»å°çè¿äºæ¥å£å®ä¹äºæ¯è¾èç Web Audio API æ åï¼ç°å¨å·²ç»è¿æ¶äºï¼èä¸å·²ç»è¢«æ°æ¥å£å代ã
JavaScriptNode
ç¨äºéè¿ç¼å JavaScript 代ç ç´æ¥å¤çé³é¢æ°æ®ï¼ç°å¨å·²ç»è¢«ScriptProcessorNode
å代ã
WaveTableNode
ç¨äºå®ä¹ä¸ä¸ªå¨ææ§æ³¢å½¢ï¼ç°å¨å·²ç»è¢«PeriodicWave
å代ã
ä¸é¢çè¿ä¸ªç¤ºä¾ä½¿ç¨äºè¾å¤ç Web Audio API æ¥å£ï¼å¯ä»¥éè¿è®¿é®ç½åæ¥æ¥çå®çæ¶æ¶è¿è¡æ åµï¼ä¹å¯ä»¥è®¿é® GitHub ä¸å®çæºä»£ç ãè¿ä¸ªç¤ºä¾éä¼å¯¹å£°é³çé³éè¿è¡æ¹åï¼æå¼é¡µé¢æ¶ï¼å¯ä»¥å ææ¬å£°å¨çé³éè°å°ä¸äºã
Web Audio API æ¥å£å¨ä¸é¢ç代ç éå·²ç»é«äº®æ¾ç¤ºã
var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // define audio context
// Webkit/blink browsers need prefix, Safari won't work without window.
var voiceSelect = document.getElementById("voice"); // select box for selecting voice effect options
var visualSelect = document.getElementById("visual"); // select box for selecting audio visualization options
var mute = document.querySelector(".mute"); // mute button
var drawVisual; // requestAnimationFrame
var analyser = audioCtx.createAnalyser();
var distortion = audioCtx.createWaveShaper();
var gainNode = audioCtx.createGain();
var biquadFilter = audioCtx.createBiquadFilter();
function makeDistortionCurve(amount) {
// function to make curve shape for distortion/wave shaper node to use
var k = typeof amount === "number" ? amount : 50,
n_samples = 44100,
curve = new Float32Array(n_samples),
deg = Math.PI / 180,
i = 0,
x;
for (; i < n_samples; ++i) {
x = (i * 2) / n_samples - 1;
curve[i] = ((3 + k) * x * 20 * deg) / (Math.PI + k * Math.abs(x));
}
return curve;
}
navigator.getUserMedia(
// constraints - only audio needed for this app
{
audio: true,
},
// Success callback
function (stream) {
source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.connect(distortion);
distortion.connect(biquadFilter);
biquadFilter.connect(gainNode);
gainNode.connect(audioCtx.destination); // connecting the different audio graph nodes together
visualize(stream);
voiceChange();
},
// Error callback
function (err) {
console.log("The following gUM error occured: " + err);
},
);
function visualize(stream) {
WIDTH = canvas.width;
HEIGHT = canvas.height;
var visualSetting = visualSelect.value;
console.log(visualSetting);
if (visualSetting == "sinewave") {
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount; // half the FFT value
var dataArray = new Uint8Array(bufferLength); // create an array to store the data
canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
function draw() {
drawVisual = requestAnimationFrame(draw);
analyser.getByteTimeDomainData(dataArray); // get waveform data and put it into the array created above
canvasCtx.fillStyle = "rgb(200, 200, 200)"; // draw wave with canvas
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
canvasCtx.lineWidth = 2;
canvasCtx.strokeStyle = "rgb(0, 0, 0)";
canvasCtx.beginPath();
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();
} else if (visualSetting == "off") {
canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
canvasCtx.fillStyle = "red";
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
}
}
function voiceChange() {
distortion.curve = new Float32Array();
biquadFilter.gain.value = 0; // reset the effects each time the voiceChange function is run
var voiceSetting = voiceSelect.value;
console.log(voiceSetting);
if (voiceSetting == "distortion") {
distortion.curve = makeDistortionCurve(400); // apply distortion to sound using waveshaper node
} else if (voiceSetting == "biquad") {
biquadFilter.type = "lowshelf";
biquadFilter.frequency.value = 1000;
biquadFilter.gain.value = 25; // apply lowshelf filter to sounds using biquad
} else if (voiceSetting == "off") {
console.log("Voice settings turned off"); // do nothing, as off option was chosen
}
}
// event listeners to change visualize and voice settings
visualSelect.onchange = function () {
window.cancelAnimationFrame(drawVisual);
visualize(stream);
};
voiceSelect.onchange = function () {
voiceChange();
};
mute.onclick = voiceMute;
function voiceMute() {
// toggle to mute and unmute sound
if (mute.id == "") {
gainNode.gain.value = 0; // gain set to 0 to mute sound
mute.id = "activated";
mute.innerHTML = "Unmute";
} else {
gainNode.gain.value = 1; // gain set to 1 to unmute sound
mute.id = "";
mute.innerHTML = "Mute";
}
}
è§è æµè§å¨å
¼å®¹æ§ ç¸å
³é¾æ¥
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