中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于Web Audio API實現音頻可視化效果的方法

發布時間:2020-06-23 15:55:43 來源:億速云 閱讀:456 作者:清晨 欄目:web開發

這篇文章將為大家詳細講解有關基于Web Audio API實現音頻可視化效果的方法,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

網頁音頻接口最有趣的特性之一它就是可以獲取頻率、波形和其它來自聲源的數據,這些數據可以被用作音頻可視化。這篇文章將解釋如何做到可視化,并提供了一些基礎使用案例。
基本概念節
要從你的音頻源獲取數據,你需要一個 AnalyserNode節點,它可以用 AudioContext.createAnalyser() 方法創建,比如:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioCtx.createAnalyser();

然后把這個節點(node)連接到你的聲源:

source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.connect(distortion);

// etc.
注意: 分析器節點(Analyser Node) 不一定輸出到另一個節點,不輸出時也可以正常使用。但前提是它必須與一個聲源相連(直接或者通過其他節點間接相連都可以)。

分析器節點(Analyser Node) 將在一個特定的頻率域里使用快速傅立葉變換(Fast Fourier Transform (FFT) )來捕獲音頻數據,這取決于你給 AnalyserNode.fftSize 屬性賦的值(如果沒有賦值,默認值為2048)。

注意: 你也可以為FFT數據縮放范圍指定一個最小值和最大值,使用AnalyserNode.minDecibels 和AnalyserNode.maxDecibels進行設置,要獲得不同數據的平均常量,使用 AnalyserNode.smoothingTimeConstant。閱讀這些頁面以獲得更多如何使用它們的信息。

要捕獲數據,你需要使用 AnalyserNode.getFloatFrequencyData()AnalyserNode.getByteFrequencyData() 方法來獲取頻率數據,用 AnalyserNode.getByteTimeDomainData() 或 AnalyserNode.getFloatTimeDomainData() 來獲取波形數據。

這些方法把數據復制進了一個特定的數組當中,所以你在調用它們之前要先創建一個新數組。第一個方法會產生一個32位浮點數組,第二個和第三個方法會產生8位無符號整型數組,因此一個標準的JavaScript數組就不能使用 —— 你需要用一個 Float32Array 或者 Uint8Array 數組,具體需要哪個視情況而定。

那么讓我們來看看例子,比如我們正在處理一個2048尺寸的FFT。我們返回 AnalyserNode.frequencyBinCount 值,它是FFT的一半,然后調用Uint8Array(),把frequencyBinCount作為它的長度參數 —— 這代表我們將對這個尺寸的FFT收集多少數據點。

analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);

要正確檢索數據并把它復制到我們的數組里,就要調用我們想要的數據收集方法,把數組作為參數傳遞給它,例如:

analyser.getByteTimeDomainData(dataArray);

現在我們就獲取了那時的音頻數據,并存到了我們的數組里,而且可以把它做成我們喜歡的可視化效果了,比如把它畫在一個HTML5 <canvas> 畫布上。

創建一個頻率條形圖節
另一種小巧的可視化方法是創建頻率條形圖,
現在讓我們來看看它是如何實現的。

首先,我們設置好解析器和空數組,之后用 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);
  }

現在我們來設置一個 barWidth 變量,它等于每一個條形的寬度。理論上用花布寬度除以條的個數就可以得到它,但是在這里我們還要乘以2.5。這是因為有很多返回的頻率區域中是沒有聲音的,我們每天聽到的大多數聲音也只是在一個很小的頻率區域當中。在條形圖中我們肯定不想看到大片的空白條,所以我們就把一些能正常顯示的條形拉寬來填充這些空白區域。

我們還要設置一個條高度變量 barHeight,還有一個 x 變量來記錄當前條形的位置。

var barWidth = (WIDTH / bufferLength) * 2.5;
var barHeight;
var x = 0;

像之前一樣,我們進入循環來遍歷 dataArray 數組中的數據。在每一次循環過程中,我們讓條形的高度 barHeight 等于數組的數值,之后根據高度設置條形的填充色(條形越高,填充色越亮),然后在橫坐標 x 處按照設置的寬度和高度的一半把條形畫出來(我們最后決定只畫高度的一半因為這樣條形看起來更美觀)。

需要多加解釋的一點是每個條形豎直方向的位置,我們在 HEIGHT-barHeight/2 的位置畫每一條,這是因為我想讓每個條形從底部向上伸出,而不是從頂部向下(如果我們把豎直位置設置為0它就會這樣畫)。所以,我們把豎直位置設置為畫布高度減去條形高度的一半,這樣每個條形就會從中間向下畫,直到畫布最底部。

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() 函數來開啟整個可視化過程。

draw();

這些代碼會帶來下面的效果:

基于Web Audio API實現音頻可視化效果的方法

源碼:

<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8"/>
 <title>可視化音樂播放器</title>
</head>
<body>
<input type="file" name="" value="" id="musicFile">
<p id="tip"></p>
<canvas id="casvased" width="500" height="500"></canvas>
</body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
//隨機變顏色
function randomRgbColor() { //隨機生成RGB顏色
 var r = Math.floor(Math.random() * 256); //隨機生成256以內r值
 var g = Math.floor(Math.random() * 256); //隨機生成256以內g值
 var b = Math.floor(Math.random() * 256); //隨機生成256以內b值
 return `rgb(${r},${g},${b})`; //返回rgb(r,g,b)格式顏色
}
//隨機數 0-255
function sum (m,n){
  var num = Math.floor(Math.random()*(m - n) + n);
 
}
console.log(sum(0,100));
console.log(sum(100,255));
//展示音頻可視化
var canvas = document.getElementById("casvased");
var canvasCtx = canvas.getContext("2d");
//首先實例化AudioContext對象 很遺憾瀏覽器不兼容,只能用兼容性寫法;audioContext用于音頻處理的接口,并且工作原理是將AudioContext創建出來的各種節點(AudioNode)相互連接,音頻數據流經這些節點并作出相應處理。
//總結就一句話 AudioContext 是音頻對象,就像 new Date()是一個時間對象一樣
var AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
if (!AudioContext) {
 alert("您的瀏覽器不支持audio API,請更換瀏覽器(chrome、firefox)再嘗試,另外本人強烈建議使用谷歌瀏覽器!")
}
var audioContext = new AudioContext();//實例化
// 總結一下接下來的步驟
// 1 先獲取音頻文件(目前只支持單個上傳)
// 2 讀取音頻文件,讀取后,獲得二進制類型的音頻文件
// 3 對讀取后的二進制文件進行解碼
$('#musicFile').change(function(){
 if (this.files.length == 0) return;
 var file = $('#musicFile')[0].files[0];//通過input上傳的音頻文件
 var fileReader = new FileReader();//使用FileReader異步讀取文件
 fileReader.readAsArrayBuffer(file);//開始讀取音頻文件
 fileReader.onload = function(e) {//讀取文件完成的回調
 //e.target.result 即為讀取的音頻文件(此文件為二進制文件)
 //下面開始解碼操作 解碼需要一定時間,這個時間應該讓用戶感知到
 var count = 0;
 $('#tip').text('開始解碼')
 var timer = setInterval(function(){
  count++;
  $('#tip').text('解碼中,已用時'+count+'秒')
 },1000)
 //開始解碼,解碼成功后執行回調函數
 audioContext.decodeAudioData(e.target.result, function(buffer) {
  clearInterval(timer)
  $('#tip').text('解碼成功,用時共計:'+count+'秒')
  // 創建AudioBufferSourceNode 用于播放解碼出來的buffer的節點
  var audioBufferSourceNode = audioContext.createBufferSource();
  // 創建AnalyserNode 用于分析音頻頻譜的節點
  var analyser = audioContext.createAnalyser();
  //fftSize (Fast Fourier Transform) 是快速傅里葉變換,一般情況下是固定值2048。具體作用是什么我也不太清除,但是經過研究,這個值可以決定音頻頻譜的密集程度。值大了,頻譜就松散,值小就密集。
  analyser.fftSize = 256;
  // 連接節點,audioContext.destination是音頻要最終輸出的目標,
  // 我們可以把它理解為聲卡。所以所有節點中的最后一個節點應該再
  // 連接到audioContext.destination才能聽到聲音。
  audioBufferSourceNode.connect(analyser);
  analyser.connect(audioContext.destination);
  console.log(audioContext.destination)
  // 播放音頻
  audioBufferSourceNode.buffer = buffer; //回調函數傳入的參數
  audioBufferSourceNode.start(); //部分瀏覽器是noteOn()函數,用法相同
  //可視化 創建數據
  // var dataArray = new Uint8Array(analyser.fftSize);
  // analyser.getByteFrequencyData(dataArray)//將數據放入數組,用來進行頻譜的可視化繪制
  // console.log(analyser.getByteFrequencyData)
  var bufferLength = analyser.frequencyBinCount;
  console.log(bufferLength);
  var dataArray = new Uint8Array(bufferLength);
  console.log(dataArray)
  canvasCtx.clearRect(0, 0, 500, 500);
  function draw() {
  drawVisual = requestAnimationFrame(draw);
  analyser.getByteFrequencyData(dataArray);
  canvasCtx.fillStyle = 'rgb(0, 0, 0)';
		//canvasCtx.fillStyle = ;
  canvasCtx.fillRect(0, 0, 500, 500);
  var barWidth = (500 / bufferLength) * 2.5;
  var barHeight;
  var x = 0;
  for(var i = 0; i < bufferLength; i++) {
   barHeight = dataArray[i];
		 //隨機數0-255 Math.floor(Math.random()*255) 
		 // 隨機數 10*Math.random()
   canvasCtx.fillStyle = 'rgb(' + (barHeight+100) + ','+Math.floor(Math.random()*(20- 120) + 120)+','+Math.floor(Math.random()*(10 - 50) + 50)+')';
   canvasCtx.fillRect(x,500-barHeight/2,barWidth,barHeight/2);
   x += barWidth + 1;
  }
  };
  draw();
 });
 }
})
</script>
</html>

關于基于Web Audio API實現音頻可視化效果的方法就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

金塔县| 那坡县| 寻乌县| 三门峡市| 金阳县| 龙川县| 讷河市| 葵青区| 汝城县| 繁峙县| 益阳市| 台山市| 乌什县| 乌海市| 中方县| 綦江县| 宜川县| 九龙县| 商洛市| 得荣县| 霍林郭勒市| 陇南市| 安化县| 洪江市| 遂平县| 黄浦区| 小金县| 泉州市| 南开区| 西安市| 遂川县| 合山市| 昌平区| 揭阳市| 高雄县| 新野县| 舟山市| 万全县| 灌阳县| 浪卡子县| 寿光市|