创建音频源
要操作哪个音频,需要在这里定义(可以定义多个音频,在一些方法的操作下可以让他们同时播放;应用软件有个雷雨背景,就可用这个实现。具体用哪些方法,往后看会说)
根据音频类型的不同(audio标签引入,麦克风,网络请求来的在线音频的arraybuffer),要用不同的方法创建
创建朴素音频源
MediaElementSourceNode:audio标签引入,使用createMediaElementSource创建音频源
振荡器OscillatorNode:使用createOscillator创建音频源
说到振荡器,可能比较陌生,可以看看这个例子 https://codepen.io/in-6026/pen/KKZdzwO
,在这个例子中我们可以通过按钮减/增声音的频率,频率越高越尖锐,越低越低沉(声音的频率的事不必多说)
这就是个简单的振荡器,OscillatorNode让我们的设备振荡出一个特定频率(频率可以自己设置)的声音,而这个声音的频率如果被画出来,那就是个正弦函数。怎么画往后看会说。这节只讲创造音频源
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
//创建振荡器,音频源来自振荡器的振荡
oscillator = audioCtx.createOscillator();
AudioBuffer:处理arraybuffer格式,使用decodeAudioData解码,再放到AudioBufferSourceNode中创建音频源
当后端发送来的是arraybuffer的时候,或者前端readerAsArraybuffer的时候就可以用audioCtx.decodeAudioData将arraybuffer格式的音频转为audioBuffer,再将audioBuffer赋予音频源的缓冲区,那音频源就有声音了
例子:https://codepen.io/in-6026/pen/wvpKWeW
audioCtx = new AudioContext()
source = audioCtx.createBufferSource()
//把arraybuffer解码成audiobuffer
audioCtx.decodeAudioData(arraybuffer, (audiobuffer) => {
//把audiobuffer赋予音频源的缓冲区
source.buffer = audiobuffer
})
source就成了音频源了
AudioBufferSourceNode:用于处理audiobuffer格式,就是把上面读出来的audioBuffer放到source.buffer里面(这个就是audioBuffer的后半部分)
source = audioCtx.createBufferSource()
//把audiobuffer赋予音频源的缓冲区
source.buffer = audiobuffer
MediaStreamAudioSourceNode:用来处理来自麦克风的音频,麦克风就要涉及WebRTC了,暂时不展开 https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API
对朴素音频源的基本控制与修饰
上面提到的各种方法创建出来的都是最朴素的音频源,其实他们还有各自的方法对音频做一些基本的处理(播放,暂停,控制音频的清晰度,振荡方式,播放完之后是否重复播放,等基本功能)
播放与暂停,这应该是最重要的事了,但是在这里控制开关的方法有些不同:
除了MediaElementSourceNode
是与关联,必须要操作video来控制播放外。其它类型的音频源播放与暂停都要靠音频源(source/oscillator)自己的方法控制。
怎么播放/暂停不必多说,来说说其它几个:
source/oscillator都是靠.start和.stop俩方法实现的开始/停止,但是:这种开始/暂停只允许执行一次,.start之后就不能再触发.start了
那这还能称之为暂停吗,显然不能。怎么解决呢?
audioContext.destination,在断开音频源之后他就顿在那里,等下次再连上的时候又继续从上次的地方放。故暂停于播放可以这样实现:
第一次放的时候必须source.start(delay: number) //这里面可传一个参数,延迟播放,单位: s
在之后的暂停/播放通过断开/连接实现
function pause() {
sourceNode.disconnect(); //断开
}
function resume() {
sourceNode.connect(audioCtx.destination); //连上继续放
}