摘要:其實這個能做的事不光是音頻可視化。其實這次寫博客之前還完善了一下,給加上了通過設(shè)備的麥克風(fēng)獲取音頻并可視化的方法。世界晚安參考基于實現(xiàn)音頻可視化效果本文作者本文鏈接利用實現(xiàn)音頻可視化
音頻可視化實現(xiàn)之后真的很酷,雖然這次只是跟著MDN上的教程學(xué)習(xí)了一下,照著Demo敲了一遍而已。但收獲頗多,記錄于此。
web audio api先來感受一下 web audio api 的基礎(chǔ)概念,下面截取一段MDN上的介紹。具體的請移步文檔
Web audio 概念與使用Web Audio API使用戶可以在音頻上下文(AudioContext)中進(jìn)行音頻操作,具有模塊化路由的特點。在音頻節(jié)點上操作進(jìn)行基礎(chǔ)的音頻, 它們連接在一起構(gòu)成音頻路由圖。即使在單個上下文中也支持多源,盡管這些音頻源具有多種不同類型通道布局。這種模塊化設(shè)計提供了靈活創(chuàng)建動態(tài)效果的復(fù)合音頻的方法。
在跟著文檔和Demo走了一遍之后,我自己的理解就是,我們可以通過const audioCtx = new (window.AudioContext || window.webkitAudioContext)()這樣的形式來獲取/創(chuàng)建一個音頻上下文,這個audioCtx中有許多可供使用的屬性方法。這里只會稍微描述一下實現(xiàn)音頻可視化要用的屬性。具體的可以參考文檔。
其實這個AudioContext能做的事不光是音頻可視化。首先它支持獲取音頻的輸入,也就是接下來會提到的定義音頻源。然后它能夠定義音效,或許你要是知道怎么把一段聲音做成電音的算法,那你可以試試,然后教教我。哈哈哈,當(dāng)然一些基礎(chǔ)的控制音頻源的輸出音量這些都是有的。
接下來就繼續(xù)談音頻可是化啦
音頻可視化首頁我們需要選擇一個用來展示音頻的工具,這里其實用的就是Canvas,當(dāng)然如果你會用Svg也可以嘗試著做一下。這里我不會svg,嗯。打算學(xué)(but, who knows when)。
那么這里就只剩下用來顯示的數(shù)據(jù)了。
前面提到過,AudioContext中有許多屬性和方法,其中就有createAnalyser()方法,可以供我們獲取AnalyserNode這個對象。這個對象會提供給我們用來顯示(可以被我們處理成用來顯示的)的所需要的數(shù)據(jù)。
AnalyserNode這里還是得簡單提一下AnalyserNode,我們接下來需要用到它的幾個屬性和方法
AnalyserNode.fftSize
一個無符號長整形(unsigned long)的值, 用于確定頻域的?FFT (快速傅里葉變換) 的大小。
AnalyserNode.getByteFrequencyData()
將當(dāng)前頻域數(shù)據(jù)拷貝進(jìn)Uint8Array數(shù)組(無符號字節(jié)數(shù)組)。
AnalyserNode.getByteTimeDomainData()
將當(dāng)前波形,或者時域數(shù)據(jù)拷貝進(jìn)?Uint8Array數(shù)組(無符號字節(jié)數(shù)組)。
這里直接copy了MDN的內(nèi)容。然后我再根據(jù)自己的理解來描述一下。
AnalyserNode.fftSize
首先我們可以通過設(shè)置AnalyserNode.fftSize來控制將要用來顯示的數(shù)據(jù)(數(shù)組,這里后面會處理成數(shù)組)的個數(shù)(長度),簡單點說就是,如果我們想用柱狀圖來顯示數(shù)據(jù),fftSize設(shè)置的越大,那我們顯示的柱子的數(shù)量就會越多。反之同理。不過這個值是有范圍的,并且必須是2的n次冪。范圍:[32, 32768],超出或小于會報錯。
AnalyserNode.getByteFrequencyData()
這個在文檔中描述是獲取當(dāng)前頻域的數(shù)據(jù),我理解成就是如果要顯示成柱狀圖的形式,那么就用這個。因為我試過了用getByteTimeDomainData結(jié)果并不是很好。因為getByteTimeDomainData是用用來展示波形的,這里我理解的就是文檔的字面意思。不展開描述
好的,這里要用到的關(guān)鍵的基礎(chǔ)知識介紹完畢。接下來就是要做事了,直接上代碼了。
實現(xiàn)一下接下來是一些供描述的代碼,具體的代碼在我的Github上,其實直接看MDN提供的Demo的源代碼也行。
// 獲取頁面中的audio對象 const myAudio = document.querySelector("audio") // 獲取web audio 上下文對象 const audioCtx = new (window.AudioContext || window.webkitAudioContext)() // 獲取聲音源 const source = audioCtx.createMediaElementSource(myAudio) // 獲取分析對象 const analyser = audioCtx.createAnalyser() // 設(shè)置fftSize analyser.fftSize = 1024 const bufferLength = analyser.fftSize // 因為這里analyser返回的數(shù)據(jù)js不能直接使用,所以要通過Uint8Array來轉(zhuǎn)換一下,讓js認(rèn)識一下 const dataArray = new Uint8Array(bufferLength) // 連接解析器 source.connect(analyser) // 輸出音頻 source.connect(audioCtx.destination)
以上就已經(jīng)可以獲取當(dāng)前audio對象所播放音頻的可供我們js使用的數(shù)據(jù)了,話有點繞,其實這里要用到的就是這個daraArray,我們需要在接下來編寫canvas的代碼中用到這個數(shù)組中的數(shù)據(jù)。
畫重點這里我踩了個坑,我一開始沒寫source.connect(audioCtx.destination)便運行了上面剩余的代碼,發(fā)現(xiàn)頁面沒有聲音,但是我如果不寫這些代碼。直接用audio標(biāo)簽autoplay,聲音是很洪亮的。但是用了上面的代碼就是沒聲音。
然后我注意到Demo中還有一句source.connect(audioCtx.destination)我沒寫。加上之后,確實出了聲音。于是我看了一下文檔得知,這個是用來定義音頻目的地的。也就是說,在我們把音頻源傳入AudioContext之后,這個音頻源就被AudioContext托管了。然后AudioContext并不會自動播放聲音,這里需要手動設(shè)置一下音頻的歸屬地(通常是輸出到你的揚聲器)
那么接下來就是把數(shù)據(jù)顯示出來了,這里我直接粘貼處理canvas的代碼了(困了,現(xiàn)在半夜12:13)
const draw = () => { // 獲取當(dāng)前聲音的波形;將當(dāng)前波形,或者時域數(shù)據(jù)拷貝進(jìn) Uint8Array數(shù)組(無符號字節(jié)數(shù)組) analyser.getByteTimeDomainData(dataArray) ctx.clearRect(0, 0, W, H) ctx.fillStyle = "rgb(200,200,200)" ctx.fillRect(0, 0, W, H) ctx.strokeStyle = "rgb(0,0,0)" ctx.beginPath() const sliceWidth = W * 1.0 / bufferLength let x = 0 for (let i = 0; i < bufferLength; i++) { let v = dataArray[i] / 128.0 let y = v * H / 2 if (i === 0) { ctx.moveTo(x, y) } else { ctx.lineTo(x, y) } x += sliceWidth } ctx.lineTo(W, H / 2) ctx.stroke() requestAnimationFrame(draw) } const draw2 = () => { // 獲取當(dāng)前頻域數(shù)據(jù);將當(dāng)前頻域數(shù)據(jù)拷貝進(jìn)Uint8Array數(shù)組(無符號字節(jié)數(shù)組) analyser.getByteTimeDomainData(dataArray) ctx.clearRect(0, 0, W, H) ctx.fillStyle = "rgb(0,0,0)" ctx.fillRect(0, 0, W, H) const barWidth = (W / bufferLength) * 2.5 let barHeight let x = 0 for (let i = 0; i < bufferLength; i++) { barHeight = dataArray[i] / 2 ctx.fillStyle = `rgb(${barHeight + 100},50,50)` ctx.fillRect(x, H - barHeight, barWidth, barHeight) x += barWidth + 1 } requestAnimationFrame(draw2) }
這里有兩個方法,分別:draw是用來顯示波形的,draw2是可以顯示成柱狀圖的樣子,我個人更喜歡draw2畫出來的樣子。
因為這次是分享web audio api,而且上面canvas的代碼比較簡單,看看就好了。就不展開講了。
最后BB了好久,就總結(jié)一下了,希望有人能看到這里。
這次知道寫web audio api 也其實就是簡單的介紹了一下這個強大的api能支持網(wǎng)頁對音頻作出來的各種騷操作。不光光是可視化,變聲,換成立體環(huán)繞啥的都是不在話下的。有興趣的同學(xué)可以了解一下。嗯,了解一下,然后教教我。
其實這次寫博客之前還完善了一下,給加上了通過設(shè)備的麥克風(fēng)獲取音頻并可視化的方法。挺簡單的,看看源碼就知道了。
或許過兩天會給這篇加上點圖片,放個demo的地址吧。
不早了 睡了。世界晚安
參考- 基于Web Audio API實現(xiàn)音頻可視化效果
- HTML5 Audio: createMediaElementSource breaks audio output
- AnalyserNode
- web audio api
本文作者: Roy Luo本文鏈接: 利用 web audio api 實現(xiàn)音頻可視化
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/97044.html
摘要:前言本文翻譯自上的利用,這是中的的一個入門教程。原文是英文,但有日本同志翻譯的日文版。這是為了提供一個基本的低音増幅效果在這個例子中可以設(shè)定過濾器的種類,周波數(shù),甚至的值。如果是過濾器的話,可以提供一個比指定周波數(shù)低的低音増幅。 前言 本文翻譯自MDN上的《Web Audio APIの利用》,這是HTML5中的Web Audio API的一個入門教程。原文是英文,但有日本同志翻譯的日文...
摘要:高動態(tài)范圍,采用進(jìn)行內(nèi)部處理。這最大限度地減少體積驟降音頻區(qū)域之間,從而導(dǎo)致更均勻的交叉衰減,可能是在電平略有不同區(qū)域之間。低通濾波器保持較低的頻率范圍,但丟棄高頻。 引用 Getting Started with Web Audio APIhttp://www.html5rocks.com/en/tutorials/webaudio/intro/ Introduction Audio...
摘要:一直覺得網(wǎng)易云音樂的用戶體驗是很不錯的,很早就注意到了里面的鯨魚音效,如下圖,就是一個環(huán)形的跟著音樂節(jié)拍跳動的特效。 一直覺得網(wǎng)易云音樂的用戶體驗是很不錯的,很早就注意到了里面的鯨魚音效,如下圖,就是一個環(huán)形的跟著音樂節(jié)拍跳動的特效。 showImg(https://segmentfault.com/img/remote/1460000017090441); gif動圖可能效果不太理想...
閱讀 3898·2021-09-27 13:36
閱讀 4637·2021-09-22 15:12
閱讀 3075·2021-09-13 10:29
閱讀 1845·2021-09-10 10:50
閱讀 2381·2021-09-03 10:43
閱讀 533·2019-08-29 17:10
閱讀 455·2019-08-26 13:52
閱讀 3271·2019-08-23 14:37