Web Audio API之手把手教你用web api處理聲音信號:可視化音樂demo

1.Web Audio API 介紹

       Web Audio API 提供了在Web上控制音頻的一個很是有效通用的系統 ,這些通用系統通俗的講就是咱們能夠利用Web Audio API提供的各類方法操做各類源中的聲音,處理聲音,使聲音可視化等。javascript

  要使用Web Audio API,咱們仍是先來簡單的瞭解一下它的工做流程:css

  1. 建立音頻環境(eg. AudioContext..)
  2. 在音頻環境裏建立源 — 例如 , 振盪器, 流(eg. navigator.getUserMedia/createMediaElementSource..)
  3. 建立效果節點,例如混響、雙二階濾波器、平移、壓縮(Web Audio API 提供一些簡單的濾波器或者延時器等,能夠製做一個簡單的混音工具)
  4. 爲音頻選擇一個目地,例如你的系統揚聲器
  5. 鏈接源到效果器,以及效果器和目地(分析和可視化eg. AnalyserNode)

       其兼容性以下:html

  桌面端java

瀏覽器 Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
支持版本 14 
23 未實現 15 6

  移動端web

 

瀏覽器chrome

Androidcanvas

Chromeapi

Firefox Mobile (Gecko)數組

Firefox OS瀏覽器

IE Phone

Opera Mobile

Safari Mobile

支持版本 未實現 28 
25 1.2 未實現 未實現

 

2.示例代碼

  "talking is cheap , show me the codes."

  我知道各位看官並不想聽什麼時域頻域變換,什麼傅立葉變換,什麼web audio api原理,那我就廢話很少說,直接放碼過來了,先看看效果再來給你們解釋。

  盡情複製粘貼,而後拿個現代一點的瀏覽器跑一下(用IE的請點右上角紅叉,謝謝)。

      注意:audio標籤的src屬性內容請本身在本機找一個瀏覽器支持的聲音源格式。

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<meta name="Author" contect="GabrielChen">
	<meta name="keywords" contect="Web Audio API">
    <title>Web Audio API 學習</title>
    <script>
        var canvas;
        var ctx;
        var audioContext;
        var analyser;
        var mic;

        function init() {
            canvasOne = document.getElementById('canvasOne');
            ctx = canvasOne.getContext("2d");
            canvasTwo = document.getElementById('canvasTwo');
            ctx2 = canvasTwo.getContext("2d");
        
            
        }
      
        navigator.getMedia = ( navigator.getUserMedia ||
                navigator.webkitGetUserMedia ||
                navigator.mozGetUserMedia ||
                navigator.msGetUserMedia);

        navigator.getMedia ( { audio: true }, function (stream) {
            audioContext = new (window.AudioContext || window.webkitAudioContext);
            
            mic = audioContext.createMediaStreamSource(stream);
           
            analyser= audioContext.createAnalyser();
           
            analyser.fftSize = 256;
            mic.connect(analyser);
            drawSpectrum();
        },function(){});

        

        function drawSpectrum() {
            var WIDTH = canvasOne.width;
            var HEIGHT= canvasOne.height;

            var array =  new Uint8Array(128);
            analyser.getByteFrequencyData(array);
            ctx.clearRect(0, 0, WIDTH, HEIGHT);
            ctx2.clearRect(0, 0, 800, 800);
            for ( var i = 0; i < (array.length); i++ ){
                var value = array[i];
                ctx.fillRect(i*5,HEIGHT-value,3,HEIGHT);
            }

          
            for ( var i = 0; i < (array.length); i++ ){
                var value = array[i];
                ctx2.beginPath();
				ctx2.arc(300,300,value,0,360,false);
				ctx2.lineWidth=5;
				ctx2.strokeStyle="rgba("+value+","+value+",0,0.2)";
				ctx2.stroke();//畫空心圓
				ctx2.closePath();
        
            }
            
            requestAnimationFrame(drawSpectrum);
        };




    </script>
    <style>
        #canvasOne {
            border: 1px solid #ddd;
        }
    </style>
</head>
<body onload="init();">
<h1>從audio源獲取聲音</h1>
<audio src="./Fatbros.ogg" controls="controls" id="audio">你的瀏覽器不支持audio標籤</audio>
<h1>audio讀取聲音</h1>
<canvas id="canvasFormAudio" width="640"></canvas>
<h1>頻域圖模仿</h1>
<canvas id="canvasOne" width="640"></canvas>
<h1>圓形聲波圖</h1>
<canvas id="canvasTwo" width="800" height="800"></canvas>

<script type="text/javascript">


        var context1;
        var source;
        var analyserfa;
        var canvasFormAudio;
        var ctxfa;

        canvasFormAudio = document.getElementById('canvasFormAudio');
        ctxfa = canvasFormAudio.getContext("2d");
        try {
       
    	 context1 = new (window.AudioContext || window.webkitAudioContext);
		} catch(e) {
    	 throw new Error('The Web Audio API is unavailable');
		}

		analyserfa=context1.createAnalyser();

		window.addEventListener('load', function(e) {
  	         var audio =document.getElementById("audio");
 		 var source = context1.createMediaElementSource(audio);
 		 source.connect(analyserfa);
  		 analyserfa.connect(context1.destination);
  	
  		 drawSpectrumfa();
  
}, false);
        function drawSpectrumfa() {
            var WIDTH = canvasFormAudio.width;
            var HEIGHT= canvasFormAudio.height;

            var array =  new Uint8Array(128);
           
            analyserfa.getByteFrequencyData(array);

            ctxfa.clearRect(0, 0, WIDTH, HEIGHT);
           
            for ( var i = 0; i < (array.length); i++ ){
                var value = array[i];
           ctxfa.fillRect(i*5,HEIGHT-value,3,HEIGHT);
            }

         	
            requestAnimationFrame(drawSpectrumfa);
        }
</script>
</body>
</html>

  

  

 

3.代碼分析

咱們從body部分入手分析

<body onload="init();">
<h1>從audio源獲取聲音</h1>
<audio src="./Fatbros.ogg" controls="controls" id="audio">你的瀏覽器不支持audio標籤</audio>
<h1>audio讀取聲音</h1>
<canvas id="canvasFormAudio" width="640"></canvas>
<h1>頻域圖模仿</h1>
<canvas id="canvasOne" width="640"></canvas>
<h1>圓形聲波圖</h1>
<canvas id="canvasTwo" width="800" height="800"></canvas>

用onload屬性調用初始化函數init(),主要在頁面生成以後初始化一些變量,避免讀不到相關DOM。

       function init() {
            canvasOne = document.getElementById('canvasOne');
            ctx = canvasOne.getContext("2d");
            canvasTwo = document.getElementById('canvasTwo');
            ctx2 = canvasTwo.getContext("2d");
        
            
        }

第一塊canvas:從audio源獲取聲音

首先一個audio標籤,在本機選定一個src,設置controls屬性表明瀏覽器顯示播放器控制頁面,設置id爲audio。

再設置一個id爲"canvasFormAudio"的畫布canvas。

<audio src="./Fatbros.ogg" controls="controls" id="audio">你的瀏覽器不支持audio標籤</audio>
<h1>audio讀取聲音</h1>
<canvas id="canvasFormAudio" width="640"></canvas>

獲取聲音源以及繪圖

//直接從audio處理音頻源,聲明一些必要的變量
        var context1;
        var source;
        var analyserfa;
        var canvasFormAudio;
        var ctxfa;
//初始化畫布
        canvasFormAudio = document.getElementById('canvasFormAudio');
        ctxfa = canvasFormAudio.getContext("2d");
//創建一個音頻環境,由於瀏覽器實現不一樣,作了一點兼容性處理 try { context1 = new (window.AudioContext || window.webkitAudioContext); } catch(e) { throw new Error('The Web Audio API is unavailable'); } //創建一個分析器 analyserfa=context1.createAnalyser(); window.addEventListener('load', function(e) { // 從audio標籤獲取聲音源 source var audio =document.getElementById("audio"); var source = context1.createMediaElementSource(audio); source.connect(analyserfa); analyserfa.connect(context1.destination); //調用繪圖函數 drawSpectrumfa(); }, false);
      //繪圖函數 function drawSpectrumfa() { var WIDTH = canvasFormAudio.width; var HEIGHT= canvasFormAudio.height; var array = new Uint8Array(128); //複製當前的頻率值到一個無符號數組中 analyserfa.getByteFrequencyData(array); //clearRect(矩形左上角x座標,矩形左上角y座標,清除矩形的寬,清除矩形的高) ctxfa.clearRect(0, 0, WIDTH, HEIGHT); //循環生成長條矩形 for ( var i = 0; i < (array.length); i++ ){ var value = array[i]; //fillRect(矩形左上角x座標,矩形左上角y座標,矩形寬,矩形高)
         //這裏咱們的array一共有128組數據,因此咱們當時canvas設置的寬度爲5*128=640 ctxfa.fillRect(i*5,HEIGHT-value,3,HEIGHT); } //根據瀏覽器頻率繪圖或者操做一些非css效果 requestAnimationFrame(drawSpectrumfa); }

  

第二塊:頻域圖模仿和圓形聲波圖

這兩個圖的音源都是利用瀏覽器調用電腦麥克風取得,因此必定要贊成瀏覽器請求的麥克風權限。

繪圖區域

<h1>頻域圖模仿</h1>
<canvas id="canvasOne" width="640"></canvas>
<h1>圓形聲波圖</h1>
<canvas id="canvasTwo" width="800" height="800"></canvas>

初始化init()函數、從麥克風獲取音源和繪圖函數

        var canvas;
        var ctx;
        var audioContext;
        var analyser;
        var mic;
//初始化兩個畫布的函數,聲明爲2d繪圖
        function init() {
            canvasOne = document.getElementById('canvasOne');
            ctx = canvasOne.getContext("2d");
            canvasTwo = document.getElementById('canvasTwo');
            ctx2 = canvasTwo.getContext("2d");
        
            
        }
       //getMedia調用參數以下,返回一個多媒體流
    //constraints可選{ video: true, audio: true },表明獲取多媒體的類型
//var stream = navigator.getUserMedia(constraints, successCallback, errorCallback); navigator.getMedia = ( navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); navigator.getMedia ( { audio: true }, function (stream) { audioContext = new (window.AudioContext || window.webkitAudioContext); //返回一個多媒體流 mic = audioContext.createMediaStreamSource(stream); //creates an AnalyserNode 建立一個分析節點 analyser= audioContext.createAnalyser(); //fftsize默認值2048,是快速傅立葉變換用於頻域分析的值,必須爲2的冪,而咱們獲得的數據一般爲其的一半,下面會說道 analyser.fftSize = 256; mic.connect(analyser);
      //調用繪圖函數 drawSpectrum(); },function(){});      //圓形聲波繪圖和矩形繪圖 function drawSpectrum() { var WIDTH = canvasOne.width; var HEIGHT= canvasOne.height;        //長度爲128無符號數組用於保存getByteFrequencyData返回的頻域數據 var array = new Uint8Array(128); analyser.getByteFrequencyData(array);
       //如下是根據頻率數據畫圖,主要爲canvas知識,不作詳細解答 ctx.clearRect(0, 0, WIDTH, HEIGHT); ctx2.clearRect(0, 0, 800, 800); for ( var i = 0; i < (array.length); i++ ){ var value = array[i]; ctx.fillRect(i*5,HEIGHT-value,3,HEIGHT); } //ctx2.clearRect(700, 700, WIDTH, HEIGHT); for ( var i = 0; i < (array.length); i++ ){ var value = array[i]; ctx2.beginPath(); ctx2.arc(300,300,value,0,360,false); ctx2.lineWidth=5; ctx2.strokeStyle="rgba("+value+","+value+",0,0.2)"; ctx2.stroke();//畫空心圓 ctx2.closePath(); } // requestAnimationFrame(drawSpectrum); };

 

4.最終效果

 

6.最新進展

  文中的getMedia方法(getUserMedia)在chrome 47後已經不能夠從非安全源訪問(Insecure Origins),即http協議,.firefox還能夠但不知道爲何有bug,幾秒鐘後就share設備失敗。

  如今chrome開發者可使用如下方法繼續在非安全源使用這個函數:

  You can run chrome with the --unsafely-treat-insecure-origin-as-secure="example.com" flag (replacing "example.com"with the origin you actually want to test), which will treat that origin as secure for this session. Note that you also need to include the --user-data-dir=/test/only/profile/dir to create a fresh testing profile for the flag to work

 

 

7.參考

1.MDN

2.api接口查詢

3.chrome

相關文章
相關標籤/搜索