è¿ç¯æç« è§£éäº ç½é¡µé³é¢æ¥å£ (Web Audio API) è¿ä½è¿ç¨ä¸çé¨åé³é¢å¤çæ¦å¿µãæ¬æå¹¶ä¸ä¼å°ä½ å为ä¸åé³é¢å¤ç大å¸ï¼ä½å®å¯ä»¥ç»ä½ è¶³å¤çèæ¯ç¥è¯æ¥çè§£ ç½é¡µé³é¢æ¥å£ çè¿è¡åçï¼å¹¶è½è®©ä½ å¨ä½¿ç¨å®æ¶ååºæ´å¥½çå³çã
é³é¢èç¹ï¼æ¨¡ååè¿æ¥ç½é¡µé³é¢æ¥å£ (Web Audio API) 主è¦å¨ é³é¢ç¯å¢ (audio context) ä¸è¿è¡é³é¢å¤çï¼å®ä¹å 许模åé´çè¿æ¥ãåºæ¬çé³é¢å¤çå¨ é³é¢èç¹ (audio node) å½ä¸è¿è¡ï¼è¿äºèç¹è¿æ¥å¨ä¸èµ·å½¢æäº é³é¢å¯¼åå¾ (audio routing graph)ãå¤ä¸ªå£°æºï¼çè³å å«ä¸åç§ç±»ç声éï¼é½å¯ä»¥å¨ä¸ä¸ªé³é¢ç¯å¢ä¸è¿è¡å¤çãè¿ç§æ¨¡ååç设计使å¾äººä»¬å¨åå»ºå¤æå¤åç声é³ç¹ææ¶å¯ä»¥æ´å çµæ´»ã
é³é¢èç¹å¯ä»¥éè¿åèªçè¾å ¥ä¸è¾åºç¸è¿ï¼å½¢æä¸ä¸ª ä»ä¸ä¸ªæå¤ä¸ªå£°æºå¼å§ï¼ç»è¿å¤çèç¹ï¼ç»æ¢äºæ«èç¹ çé¾å¼ç»æï¼ææ¶ä½ ä¸éè¦æ«èç¹ï¼æ¯å¦ä½ åªæ¯æ³æ°ååå¤çæäºé³é¢æ°æ®çæ¶åï¼ãä¸ä¸ªç®åãå ¸åçç½é¡µé³é¢æ¥å£çæä½æµç¨å¯ä»¥æ¯è¿æ ·çï¼
<audio>
æ ç¾ï¼æ¯å¨åå£°å¨ (oscillator)ï¼é³é¢æµæ¯ä¸ªè¾å ¥åè¾åºé½å¯ä»¥å æ¬å 个声éï¼å£°é代表äºä¸ä¸ªç¹å®ç鳿ééãåç§å£°éåç¦»ç»æé½å¯ä»¥ä½¿ç¨ï¼å æ¬å声éï¼ç«ä½å£°ï¼å声éï¼5.1ççã
声æºå¯ä»¥æ¥èªä¸åçå°æ¹ï¼
<video>
æè
<audio>
æ ç¾ï¼MediaStream
è·åæµåªä½ï¼ä¾å¦ä¸ä¸ªæå头æéº¦å
é£ï¼å½ä¸ä¸ªé³é¢ä¿¡å·è¢«å¤çæ¶ï¼åæ ·æå³çä»ä¸ä¸ªè¿ç»çä¿¡å·è½¬å为离æ£çä¿¡å·ï¼æ´å ·ä½å°è¯´ï¼ä¸ä¸ªè¿ç»ç声波ï¼ä¾å¦ä¸ä¸ªæ£å¨æ¼å¥çä¹éååºç声é³ï¼ä¼è¢«è½¬åæä¸ç³»åçæ ·æ¬ç¹ï¼ä¸ä¸ªæ¶é´ä¸ç¦»æ£çä¿¡å·ï¼ï¼è®¡ç®æºåªå¯ä»¥å¤çè¿äºç¦»æ£çæ ·æ¬åã
æ´å¤çç»èå¯ä»¥æ¥çç»´åºç¾ç§çéæ ·é¡µé¢ã
é³é¢ç段ï¼å¸§ãæ ·æ¬å声éä¸ä¸ªé³é¢ç段ï¼AudioBuffer
ï¼ä¼å
å«å ä¸ªç»æåæ°ï¼ä¸ä¸ªæå 个声éï¼1 代表å声éï¼2 代表ç«ä½å£°ççï¼ï¼ä¸ä¸ªé¿åº¦ï¼ä»£è¡¨ç段ä¸éæ ·å¸§çæ°ç®ï¼åä¸ä¸ªéæ ·çï¼æ¯æ¯ç§ééæ ·å¸§ç个æ°ï¼ã
æ¯ä¸ªæ ·æ¬ç¹é½æ¯ä¸ä¸ª 代表ç该é³é¢æµå¨ç¹å®æ¶é´ç¹å®å£°éä¸çæ°å¼ç åç²¾åº¦æµ®ç¹æ°ãä¸ä¸ªå¸§ï¼æè ä¸ä¸ªéæ ·å¸§æ¯ç±ä¸ç»å¨ç¹å®æ¶é´ä¸çææå£°éçæ ·æ¬ç¹ç»æçââ峿æå£°éå¨å䏿¶é´çæ ·æ¬ç¹ï¼ç«ä½å£°æ 2 个ï¼5.1æ 6 个ï¼ççï¼æ¯ä¸ªå¸§å å«çæ ·æ¬ç¹ä¸ªæ°å声鿰ç¸åï¼ã
éæ ·çå°±æ¯ä¸ç§éå è·å帧ç个æ°ï¼å使¯èµ«å ¹ï¼Hzï¼ãéæ ·çè¶é«ï¼é³é¢ææè¶å¥½ã
ç°å¨è®©æä»¬æ¥çä¸ä¸ééï¼ä¸ä¸ªå声éåä¸ä¸ªç«ä½å£°çé³é¢çæ®µï¼æ¯ä¸ªé½æ¯ 1 ç§éï¼ææ¾é¢çï¼éæ ·çï¼ä¸º 44100 èµ«å ¹ï¼
å½ä¸ä¸ªé³é¢ç段å¼å§ææ¾æ¶ï¼ä½ å°ä¼å¬å°æå·¦ä¾§çæ ·æ¬å¸§ï¼ä¹åæ¯ä»å³ä¾§ç¸é»çä¸å¸§ï¼ä»¥æ¤ç±»æ¨ãå¨ç«ä½å£°ä¸ï¼ä½ å°ä¼åæ¶å¬å°ä¸¤ä¸ªå£°éãæ ·æ¬å¸§çæ¦å¿µå¨æ¤æ¶é常æç¨ï¼å 为æ¯ä¸ªæ ·æ¬å¸§ä»£è¡¨ç¹å®çææ¾æ¶é´ï¼èå声éä¸ªæ°æ å ³ï¼è¿ç§æ¹å¼å¾æå©äºç²¾ç¡®çå¤å£°é忥å¤çã
夿³¨ï¼ åªéç¨å¸§çæ°ç®é¤ä»¥éæ ·çå³å¯å¾å°ææ¾æ¶é´ï¼åä½ä¸ºç§ï¼ãç¨æ ·æ¬ç¹æ°ç®é¤ä»¥å£°é个æ°å³å¯å¾å°å¸§çæ°ç®ã
ä¸é¢æä»¬å°å±ç¤ºå ä¸ªæµ æ¾ææç示ä¾ï¼
var context = new AudioContext();
var buffer = context.createBuffer(2, 22050, 44100);
å¦æä½ ä½¿ç¨ä¸é¢çæ¹æ³è°ç¨ï¼ä½ å°ä¼å¾å°ä¸ä¸ªç«ä½å£°ï¼ä¸¤ä¸ªå£°éï¼çé³é¢ç段 (Buffer)ï¼å½å®å¨ä¸ä¸ªé¢ç为 44100 èµ«å ¹ï¼è¿æ¯ç®å大é¨å声å¡å¤ç声é³çé¢çï¼çé³é¢ç¯å¢ä¸ææ¾çæ¶åï¼ä¼æç» 0.5 ç§ï¼22050 帧 / 44100 èµ«å ¹ = 0.5 ç§ã
夿³¨ï¼ 卿°åé³é¢ä¸ï¼44,100 èµ«å ¹ï¼ææ¶ä¹åä½ 44.1 kHzï¼æ¯ä¸ä¸ªå¸¸è§çéæ ·é¢çã为ä»ä¹éå 44.1kHz å¢ï¼é¦å ï¼å 为人è³çæ¥æ¶é¢çå¤§çº¦å¨ 20 Hz å° 20,000 Hz ä¹é´ï¼æ ¹æ®éæ ·å®çï¼éæ ·é¢çä¸å®è¦å¤§äºæç»çææ°æ®æå¤§é¢ççäºåï¼å æ¤å°±ä¸å®è¦å¤§äº 40,000 Hzï¼å³ 40kHzï¼ãä¸ä» 妿¤ï¼å¨éæ ·ä¹åä¿¡å·è¿å¿ é¡»éè¿ä½é滤波å¨ï¼å¦å ä¼åçæ··å ç°è±¡ï¼ä¸ä¸ªçæ³ä½é滤波å¨ä¼å®å ¨çä¸ä½äº 20kHz çä¿¡å·ï¼ä¸æ²¡æä½¿å®è¡°åï¼å¹¶å®ç¾é»æ¦ä¸åé«äº 20kHz çä¿¡å·ï¼èäºå®ä¸è¿åº¦é¢å¸¦æ»æ¯åå¨ï¼å¨è¿ä¸ªåºåå ä¿¡å·ä¼è¢«é¨åè¡°åãè¿ä¸ªé¢å¸¦è¶å®½ï¼å»ºç«ä¸ä¸ªææ··å æ»¤æ³¢å¨æè¶å®¹æãå æ¤æä»¬éå 44.1kHz å 许æä»¬æ 2.05kHz ç空é´é¢çç»è¿åº¦é¢å¸¦ã
var context = new AudioContext();
var buffer = context.createBuffer(1, 22050, 22050);
å¦æä½ è¿æ ·è°ç¨ï¼ä½ å°ä¼å¾å°ä¸ä¸ªå声éçé³é¢ç段 (Buffer)ï¼å½å®å¨ä¸ä¸ªé¢ç为 44100 èµ«å ¹çé³é¢ç¯å¢ä¸ææ¾çæ¶åï¼å°ä¼è¢«èªå¨æç § 44100 èµ«å ¹ééæ ·ï¼å æ¤ä¹ä¼è½¬å为 44100 èµ«å ¹ççæ®µï¼ï¼å¹¶æç» 1 ç§ï¼44100 帧 / 44100 èµ«å ¹ = 1 ç§ã
夿³¨ï¼ é³é¢ééæ ·ä¸å¾çç缩æ¾éå¸¸ç±»ä¼¼ï¼æ¯å¦ä½ æä¸ä¸ª 16 x 16 çå¾åï¼ä½æ¯ä½ æ³æå®å¡«å å°ä¸ä¸ª 32 x 32 大å°çåºåï¼ä½ å°±è¦å¯¹å®è¿è¡ç¼©æ¾ï¼ééæ ·ï¼ãå¾å°çç»æä¼æ¯ä¸ä¸ªè¾ä½åè´¨çï¼å¾å伿¨¡ç³æè æé¯é½¿å½¢çè¾¹ç¼ï¼è¿åå³äºç¼©æ¾éç¨çç®æ³ï¼ï¼ä½å®å´æ¯è½å°åå¾å½¢ç¼©æ¾ï¼å¹¶ä¸ç¼©æ¾åçå¾åå ç¨ç©ºé´æ¯ç¸å大å°çæ®éå¾åè¦å°ãéæ°éæ ·çé³é¢éçç¸åââä½ ä¼è约ä¸äºç©ºé´ï¼ä½äºå®ä¸ä½ æ æ³äº§åºé«é¢çç声é³ï¼é«é³åºï¼ã
å离å¼ä¸äº¤éå¼é³é¢ç段ç½é¡µé³é¢æ¥å£ä½¿ç¨äºå离å¼ççæ®µå¨åæ¹å¼ï¼å·¦ (L) å³ (R) 声éåè¿æ ·åå¨ï¼
LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRï¼å¯¹äºä¸ä¸ªæ 16 帧çé³é¢ç段ï¼
è¿ç§å¨åæ¹å¼å¨é³é¢å¤çä¸é常常è§ï¼è¿ç§æ¹å¼å 许对æ¯ä¸ªå£°éåç¬å¤çã
å¦ä¸ç§å¨åæ¹å¼æ¯ä½¿ç¨äº¤éå¼ççæ®µå¨åæ¹å¼ï¼
LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRï¼å¯¹äºä¸ä¸ªæ 16 帧çé³é¢ç段ï¼
è¿ç§æ¹å¼å¨åå¨ä»¥åææ¾é³é¢çä¸éè¦é³é¢å å·¥çæä½ä¸é常常è§ï¼ä¾å¦ä¸ä¸ªè§£ç åç MP3 æµåªä½ã
å¨å¼åè æ¥è§¦å°çç½é¡µé³é¢æ¥å£ä¸åªæå离å¼é³é¢ç段ï¼å 为å®ä¸»è¦ç¨äºé³é¢å å·¥ãå¨å¤çè¿ç¨ä¸å®ä½¿ç¨å离å¼ï¼ä½æ¯å½å®ä¼ éå°å£°å¡ä¸ç¨äºææ¾æ¶ï¼é³é¢ç段ä¼è¢«è½¬å为交éå¼ãåè¿æ¥ï¼å½ MP3 è¢«è§£ç æ¶ï¼åå§ç¶æå®æ¯äº¤éå¼çï¼ä½æ¯ä»ä¼è¢«è½¬åæå离å¼ä»¥ç¨äºé³é¢å å·¥ã
声éä¸åçé³é¢ç段å¯è½å å«ä¸åæ°éç声é个æ°ï¼ä»åºæ¬çå声éï¼åªæä¸ä¸ªå£°éï¼ï¼ç«ä½å£°ï¼å·¦å³ä¸¤ä¸ªå£°éï¼ï¼å°æ´å 夿çå声éï¼5.1ãç±äºæ¯ä¸ªå£°éä¸å å«çé³é¢æ°æ®å¯ä»¥ä¸åï¼å æ¤å£°éè¶å¤å¬è§ææè¶å¥½ãå¨ä¸å声鿍¡å¼ä¸ï¼è¡¨ç¤ºç¹å®å£°éç缩åå¦ä¸è¡¨æç¤ºï¼
å声é0: M: å¯ä¸å£°é
Mono 0: M: mono
ç«ä½å£° 0: L: å·¦ 1: R: å³
Stereo 0: L: left 1: R: right
å声é 0: L: å·¦ 1: R: å³ 2: SL: ç¯ç»å·¦ 3: SR: ç¯ç»å³
Quad 0: L: left 1: R: right 2: SL: surround left 3: SR: surround right
5.1 0: L: å·¦ 1: R: å³ 2: C: ä¸å¤® 3: LFE: ä½é³ç® 4: SL: ç¯ç»å·¦ 5: SR: ç¯ç»å³
5.1 0: L: left 1: R: right 2: C: center 3: LFE: subwoofer 4: SL: surround left 5: SR: surround right
夿³¨ï¼ ç±äºç¼©åæ¥èªè±æï¼å æ¤ä¿çè±æä½å¯¹ç §ã
åä¸åå䏿··é¢å½è¾å
¥ä¸è¾åºç声鿰ä¸åæ¶ï¼æä»¬å°±éè¦æç
§å¦ä¸æ¹æ³è¿è¡æ··é¢ãè¿äºå°è£
å¥½çæ¹æ³å¯ä»¥éè¿è®¾ç½®å£°é³èç¹ç AudioNode.channelInterpretation
屿§ä¸º "speakers"
ï¼æ¬å£°å¨ï¼æ "discrete"
ï¼ç¦»æ£å£°éï¼è¿è¡æ··é¢ã
speakers
ï¼æ¬å£°å¨ï¼
1
ï¼å声éï¼
2
output.L = input.M
output.R = input.M
1
output.L = input.M
output.R = input.M
output.SL = 0
output.SR = 0
1
ä»å声éå° 5.1 çå䏿··é¢ã
å¯ä¸çè¾å
¥å£°éï¼Mï¼ä¼è¢«åæ¶ç¨äºä¸å¤®å£°éï¼Cï¼ã
å
¶ä½ææå£°éï¼Lï¼Rï¼LFEï¼SLï¼SRï¼é½å°ä¿æéé³ãoutput.L = 0
output.R = 0output.C = input.M
output.LFE = 0
output.SL = 0
output.SR = 0
2
1
output.M = 0.5 * (input.L + input.R)
2
output.L = input.L
output.R = input.R
output.SL = 0
output.SR = 0
2
output.L = input.L
output.R = input.R
output.C = 0
output.LFE = 0
output.SL = 0
output.SR = 0
4
1
output.M = 0.25 * (input.L + input.R +
input.SL + input.SR
)
4
2
output.L = 0.5 * (input.L + input.SL
)
output.R = 0.5 * (input.R + input.SR
)
4
output.L = input.L
output.R = input.R
output.C = 0
output.LFE = 0
output.SL = input.SL
output.SR = input.SR
6
1
â2/2ï¼å³ 1/â2
ï¼çº¦çäº 0.7071ï¼
ï¼
output.M = 0.7071 * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR)
6
2
â2/2
ï¼åä¸è¾å
¥çåä¾§éç¯ç»å£°éï¼L æ Rï¼æ··åå¾å°ã
output.L = input.L + 0.7071 * (input.C + input.SL)
output.R = input.R + 0.7071 * (input.C + input.SR)
6
output.L = input.L + 0.7071 * input.C
output.R = input.R + 0.7071 * input.C
output.SL = input.SL
output.SR = input.SR
å
¶ä»ï¼éæ å声éé
ç½®
éæ åç声éé
ç½®è¾å
¥å°ä¼è¢«æç
§ channelInterpretation
屿§è®¾ç½®ä¸º discrete
æ¶çæ
åµå¤çã
W3C è§èä¸æç¡®æåºå è®¸æªæ¥å®ä¹æ°ç声éé ç½®æ åï¼å æ¤æªæ¥å¨æµè§å¨ä¸ä½¿ç¨æ¤é¡¹çè¾åºç»æå¯è½ä¸ç°å¨ä¸ç¸åã
discrete
ï¼ç¦»æ£å£°éï¼
ä»»æx<y
å䏿··é¢ç¦»æ£ç声éã
x>y
å䏿··é¢ç¦»æ£ç声éã
ä¸è¬æ¥è¯´ï¼å¯è§åæ¯éè¿è·åå个æ¶é´ä¸çé³é¢æ°æ®ï¼éå¸¸æ¯æ¯å¹
æé¢çï¼ï¼ä¹åè¿ç¨å¾åææ¯å°å
¶å¤ç为è§è§è¾åºï¼ä¾å¦ä¸ä¸ªå¾åï¼æ¥å®ç°çãç½é¡µé³é¢æ¥å£æä¾äºä¸ä¸ªä¸ä¼æ¹åè¾å
¥ä¿¡å·çé³é¢èç¹ AnalyserNode
ï¼éè¿å®å¯ä»¥è·å声鳿°æ®å¹¶ä¼ éå°å <canvas>
çç䏿 ·çå¯è§åå·¥å
·ã
ä½ å¯ä»¥éè¿å¦ä¸æ¹æ³è·åéè¦çé³é¢æ°æ®ï¼
AnalyserNode.getFloatFrequencyData()
è¿åä¸ä¸ªFloat32Array
æ°ç»ï¼å
¶ä¸å
å«ä¼ éå°æ¤é³é¢èç¹å£°é³ç宿¶é¢çæ°æ®ã
AnalyserNode.getByteFrequencyData()
è¿åä¸ä¸ªUint8Array
æ 符å·åèæ°ç» (unsigned byte array)ï¼å
¶ä¸å
å«ä¼ éå°æ¤é³é¢èç¹å£°é³ç宿¶é¢çæ°æ®ã
AnalyserNode.getFloatTimeDomainData()
è¿åä¸ä¸ªFloat32Array
æ°ç»ï¼å
¶ä¸å
å«ä¼ éå°æ¤é³é¢èç¹å£°é³ç宿¶æ³¢å½¢ï¼æ¶é´æ°æ®ã
AnalyserNode.getByteTimeDomainData()
è¿åä¸ä¸ªUint8Array
æ 符å·åèæ°ç» (unsigned byte array)ï¼å
¶ä¸å
å«ä¼ éå°æ¤é³é¢èç¹å£°é³ç宿¶æ³¢å½¢ï¼æ¶é´æ°æ®ã
夿³¨ï¼ æ´å¤ä¿¡æ¯å¯ä»¥åèæä»¬çè¿ç¯æç« ï¼åºäº Web Audio API å®ç°é³é¢å¯è§åææã
空é´ä½ç½®åé³é¢ç空é´åï¼ç±ç½é¡µé³é¢æ¥å£ç PannerNode
å AudioListener
èç¹å¤çï¼å
许æä»¬å¯¹ç©ºé´ä¸æä¸ç¹çé³é¢ä¿¡å·ï¼ä»¥åè¿ä¸ä¿¡å·çæ¥å¬è
建ç«ä½ç½®åè¡ä¸ºæ¨¡åã
å£°ç¸æ§å¶å¨çä½ç½®å¯ä»¥éè¿ç¬å¡å°åæ ç³»è¿è¡æè¿°ï¼æ§å¶å¨çè¿å¨å¯ä»¥ç±é度åéæ¥è¡¨ç¤ºï¼è¿ä¼å¼èµ·å¤æ®åæåºï¼å®çä¼ ææ¹åå¯ä»¥ç¨ä¸ä¸ªæ¹åå饿¥è¡¨ç¤ºï¼å½å®æ¯ä¸ä¸ªå ¨æ¹åå£°æºæ¶ï¼åé¥ä¼åå¾é常大ã
æ¥å¬è çä½ç½®å¯ä»¥ç¨ç¬å¡å°åæ ç³»æ¥è¡¨ç¤ºï¼ä»çè¿å¨å¯ä»¥ç¨æ¹ååé表示ï¼å¤´é¨å§¿æå¯ä»¥ç¨ä¸¤ä¸ªåé表示ï¼ä¸ä¸ªåä¸åé表示头顶æ£å¯¹çæ¹åï¼ä¸ä¸ªåååéè¡¨ç¤ºé¼»åææåçæ¹åï¼é¢åçæ¹åï¼ï¼è¿ä¸¤ä¸ªåéåºè¯¥äºç¸åç´ã
夿³¨ï¼ æ´å¤ä¿¡æ¯å¯ä»¥åèæä»¬çè¿ç¯æç« ï¼ç½ç»é³é¢ä½ç½®ç©ºé´åå ¥é¨ã
æå ¥ä¸æåºå¯¹äºé³é¢æ¥è¯´ï¼æå
¥æ¯æ ChannelMergerNode
èç¹æ¥æ¶ä¸ç³»åå声éè¾å
¥å£°æºï¼å¹¶å°å®ä»¬æ´åè¾åºä¸ºä¸ä¸ªå¤å£°éé³é¢ä¿¡å·çè¿ç¨ï¼
æåºæ°æ°ç¸åï¼æ¯æä¸ä¸ªChannelSplitterNode
èç¹æ¥æ¶ä¸ä¸ªå¤å£°éè¾å
¥å£°æºå¹¶å°å®å离æå¤ä¸ªå声éé³é¢ä¿¡å·çè¿ç¨ï¼
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