前些年吹過一陣canvas制作html5游戲的東風,相信不少同學重溫了一把高中物理課本上的牛頓定律。時光如梭,你是否還記得牛頓定律后面一章的各種機械波的物理定律?環視四周,光纖、wifi、藍牙、廣播都有波的身影,可以說機械波橋接了信息時代。Jsonic作為前端的音頻交互框架,也有利用聲波進行數據傳輸的接口,在介紹API之前,先分享一些web audio原生編碼的干貨。
讀了這系列前兩篇博文搖滾吧HTML5!有聲前端交互!(一)和搖滾吧HTML5!有聲前端交互!(Hello, Jsonic!)的同學,應該已經能夠使用web audio產生一個特定頻率的聲波了。所謂的超聲波,就是頻率超過20000hz的聲波,正常成人人耳能接收的聲波范圍是20-20000hz。20hz以下的次聲波因為頻率和人體一些器官相近,可能對人體造成損傷,所以不建議使用。這么一看,發出超聲波就很簡單了,代碼如下,使用oscillaor節點。
var context = new webkitAudioContext(), osc = context.createOscillator(); osc.frequency.value = 20000; osc.connect(context.destination); osc.start(0);
這里有一點值得注意,oscillator節點的start方法只能調用一次。一旦調用了oscillator的stop方法,想要再發出這個頻率的聲音,就只能再創建一個新的對象了。在web audio中,我們還可以使用gain節點配合oscillator的方法,定期發出指定的聲波。你可以把gain節點理解為一個信號強度調節器,通過設置gain.gain.value的值,可以控制信號的強弱。這個值取值范圍是0~1。玩過音箱,效果器這些東西的同學應該就比較好理解了,其實web audio可以串聯各種效果的節點。(下圖僅供參考)
回到代碼的世界:
var context = new webkitAudioContext(), gain = _ctx.createGain(), osc = context.createOscillator(); osc.frequency.value =20000; gain.gain.value=0; osc.connect(gain); gain.connect(context .destination); osc.start(0); gain.gain.setValueAtTime(1,1); gain.gain.setValueAtTime(0,2);
通過以上代碼,可以在1-2秒這個時間區間內發出一個20000hz的超聲波信號。這里調用setValueAtTime方法改變gain節點的值,波形變化過程如下圖所示。gain節點有各種不同的方法,這些方法使信號強度到達預設值有不同的變化過程,讀者可自行查閱web audio的API。
通過gain節點控制信號和直接使用oscillator的start和stop方法控制信號各有利弊,具體使用大家可自行考慮。有了信號源,接下來就是接收的問題了。很多文章都介紹過html5的音頻可視化,其核心就是通過analyser節點獲取數據。這里簡單羅列下analyser節點獲取數據的幾種方法。
//通過浮點數組獲取時域數據 var data = new Float32Array(analyser.fftSize); analyser.getFloatTimeDomainData(data); //通過浮點數組獲取頻域數據 var data = new Float32Array(analyser.fftSize); analyser.getFloatFrequencyData(data); //通過 Uint8數組獲取時域數據 var data = new Uint8Array(analyser.fftSize); analyser.getByteTimeDomainData(data); //通過 Uint8數組獲取頻域數據 var data = new Uint8Array(analyser.fftSize); analyser.getByteFrequencyData(data);
時域信號和頻域信號可以通過傅里葉變化互相轉換,Jsonic選擇的是unit8數組獲取頻域信號,以下是獲取頻域數據的代碼。
var ctx = new webkitAudioContext(); navigator.webkitGetUserMedia({ audio:{optional:[{echoCancellation:false}]} },function(stream){ var analyser = ctx.createAnalyser(), _input = ctx.createMediaStreamSource(stream), data = new Float32Array(analyser.fftSize); _input.connect(analyser); analyser.getFloatFrequencyData(data); },function(e){});
這里的data數組獲取的是所有頻率的數據,那么怎么找到對應的頻率數據呢?又要上物理課了。。。。。。這里要用到 奈奎斯特定理,不懂的同學可以直接看公式B=2W。通過audioContext節點sampleRate屬性,我們可以獲取在當前web audio上下文的采樣率(一般是192000),那么通過奈奎斯特定理,這個采樣率/2就是我們能采集到的信號頻率的范圍了。上面我們采集到的data數組長度默認是1024。以192000的采樣率為例,data數組就是把0-96000hz的聲波數據均分成1024個頻率存儲。到這里我們就能獲取到頻率數據了。雖然采樣范圍很廣,但是不同設備通過oscillator節點能產生的聲波的頻率極限不同,我之前用iphone5測試的時候在22500hz左右。
下面簡單介紹下怎么用Jsonic收發超聲波數據,更多信息可以自行去搗鼓jsonic.net。
在jsonic之前的版本中,使用的是峰值分析法解碼數據。最近發布了新的版本,使用的是波形分析法,使用了新的Band對象。無論接收還是發送端,在Jsonic中都要創建一個band實例。
var band = new Jsonic.Band(); band.initDefaultChannel();
接收端 demo (點擊start按鈕后,需要授權瀏覽器使用麥克風)
navigator.webkitGetUserMedia({ audio:{optional:[{echoCancellation:false}]} },function(stream){ _input = band.AudioContext.createMediaStreamSource(stream); band.listenSource(_input); band.scanEnvironment(); },function(e){});
發射端 demo (功放,發射輸入框中的文字)
band.send('Hello Jsonic',function(){ //call back });
最后附上github地址 https://github.com/ArthusLiang/jsonic 走過路過,給個star :),同時也期待前端大神加盟。
轉發請注明出處:http://www.cnblogs.com/Arthus/p/4281442.html