如果想做一个网页端的小钢琴,可能最先想到的都是用很多个video标签,js直接控制这些video的播放和暂停,不过不仅很麻烦要录制每个琴键的声音,多个按键同时按下同时播放的兼容性也很拉
既然确定了不用video,那自然是用AudioContext
创建一个音频上下文了。让我们看一下MDN中怎么介绍AudioContext
:
AudioContext
接口表示由链接在一起的音频模块构建的音频处理图,每个模块由一个AudioNode
表示。音频上下文控制它包含的节点的创建和音频处理或解码的执行。
好嘛,还挺难懂。简单地说,AudioContext
创建了一条无限长的时间轴,时间轴上分布着声音信息(可以理解为频谱),并且不可以停止。我们可以通过时间点改编这些信息,从而控制频率、音色等等。
那么就来看看AudioContext
:
构造方法:直接new,接受一个参数,一般不写参数,默认就可以了
注:必须存储音频源。有 3 种主要类型的音频源。
属性:继承BaseAudioContext,里面比较常用的有:
属性 | 意义 |
---|---|
currentTime | 当前时间 |
state | 当前状态 |
desination | 音频播放的扬声器 |
控制音频的部分方法:
属性 | 意义 |
---|---|
AudioContext.close() | 释放AudioContext控制的资源(比如扬声器)可以理解为停止 |
AudioContext.createMediaElementSource() | 控制与标签 |
AudioContext.createMediaStreamSource() | 处理麦克风 |
AudioContext.createMediaStreamDestination() | 处理本地文件 |
AudioContext.createMediaStreamTrackSource() | 跟踪media stream |
AudioContext.getOutputTimestamp() | 返回时间戳 |
AudioContext.resume() | 暂停后的播放 |
AudioContext.suspend() | 暂停(有人翻译做挂起,不过suspend也有暂停的意思,应该更合适一些) |
于是我们可以构建出来一个利用AudioContext
的播放链:
开始播放new AudioContext => 暂停AudioContext.suspend()=> 继续播放AudioContext.resume()=>停止AudioContext.close()
并且用AudioContext.currentTime控制播放时间
我们之前已经提到过,AudioContext
必须要有音频源,接下来有一些定式的操作,获取音频源:
AudioContext.createGain()
也是AudioContext
的一个方法,创建一个GainNode,控制音频的总音量
我们要将他绑定在一个扬声器上。使用connect
方法绑定扬声器,我们就绑定默认扬声器connect(AudioContext.desination)
直接Gain.value就好了
linearRampToValueAtTime()
gain.linearRampToValueAtTime(0.6,AudioContext.currentTime + 0.01) //在0.01s内从音高从value值变到0.6
这里提一点,linearRampToValueAtTime的参数中第二个是一个时间点,表示从现在这个点到参数中的时间点内修改音高。
综上,我们创建好了一个舒舒服服的AudioContext(似乎并不舒服)
我们获取了一个AudioContext,但只有一个AudioContext有什么用(嫌弃)
我们来给他绑定音频源。因为要做钢琴,肯定是绑定振荡器了
振荡器由createOscillator
方法构造AudioContext.createOscillator()
即可创建。
创建完之后,需要连接上文创建的Gain,否则没有音量控制器,不会出声。连接用connect
方法,非常容易:
Oscillator.connect(Gain)
振荡器的属性type,代表了音频的波形,有这几个参数:
除此之外的属性frequency.value
代表了声音的频率,确定了波形和频率,即可确定某个声音。
在这里补充一下乐理基础:
var son1=new AudioContext(); //创建AudioContext var osc = son1.createOscillator() //创建音频振荡器 var g = son1.createGain() //获得音量控制器Gain osc.connect(g) //振荡器连接Gain osc.type = 'sine' //设置波形 osc.frequency.value = 440 //设置频率为440Hz,即中音la g.connect(son1.destination) //连接扬声器 g.gain.value = 1 //初始音高为1 osc.start(); //从时间轴的此时此刻当前开始发生
直接执行这段,会是一个非常刺耳的无限长的laaaaaa—————,我们再加一个截止时间
var stoptime = 1 osc.stop(stoptime);
就只响一秒了。
到这里就已经基本结束了(大概),我们来封装一下:
JS Bin - Collaborative JavaScript Debugging
代码都放这里啦
(对!就是光遇哈哈哈哈哈哈哈)