C/C++教程

做个小钢琴~利用AudioContext获取振荡器并封装成光遇钢琴的样子

本文主要是介绍做个小钢琴~利用AudioContext获取振荡器并封装成光遇钢琴的样子,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

如果想做一个网页端的小钢琴,可能最先想到的都是用很多个video标签,js直接控制这些video的播放和暂停,不过不仅很麻烦要录制每个琴键的声音,多个按键同时按下同时播放的兼容性也很拉
既然确定了不用video,那自然是用AudioContext创建一个音频上下文了。让我们看一下MDN中怎么介绍AudioContext

AudioContext接口表示由链接在一起的音频模块构建的音频处理图,每个模块由一个AudioNode表示。音频上下文控制它包含的节点的创建和音频处理或解码的执行。

好嘛,还挺难懂。简单地说,AudioContext创建了一条无限长的时间轴,时间轴上分布着声音信息(可以理解为频谱),并且不可以停止。我们可以通过时间点改编这些信息,从而控制频率、音色等等。

认识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必须要有音频源,接下来有一些定式的操作,获取音频源:

createGain()

AudioContext.createGain()也是AudioContext的一个方法,创建一个GainNode,控制音频的总音量

1.绑定扬声器

我们要将他绑定在一个扬声器上。使用connect方法绑定扬声器,我们就绑定默认扬声器connect(AudioContext.desination)

2.设置音高

直接Gain.value就好了

3.动态修改音高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,代表了音频的波形,有这几个参数:

  • sine:默认值,正弦波
  • square:方形波
  • sawtooth:锯齿波
  • triangle:三角波

除此之外的属性frequency.value代表了声音的频率,确定了波形和频率,即可确定某个声音。

在这里补充一下乐理基础:

  1. 频率为波形的一个最小重复单元的长度,单位为Hz
  2. 第一国际音高为机械波440Hz,对应中音la,高音la为440折半,220,低音la为880(这里的高和低特指的是高八度和低八度),不过纯数字算出来的频率会让人听上去音调偏低
  3. 按照第一国际音高,从低8dao,到高8dao的频率约等于[130,147,165,175,196,220,246,262,294,330,349,392,440,494,523,587,659,698,784,880,988,1047](加粗标出了基准点)
    有了频率,我们就能直接获得声音了。让我们先写几个最简单的练练手:
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
代码都放这里啦
(对!就是光遇哈哈哈哈哈哈哈)

这篇关于做个小钢琴~利用AudioContext获取振荡器并封装成光遇钢琴的样子的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!