#1 浏览器 make sound

web audio apis 种类丰富,看这些apis纯属个人兴趣,没事折腾一下。
比较好的网站:

  1. learning-web-audio-api
  2. Get start with web audio api
  3. web audio school && web-audio-school github
  4. web audio tool
  5. MDN web audio api

本文就是链接3中的一些笔记:

基础介绍

web audio api提供了很多控制音频的apis.允许开发者选取音频源,添加音频效果,创建音频可视化,应用空间效果等。

1.创建AudioContext

这是是用来链接一系列节点,从而形成一条信号链(singal path):

Inputs --> Effects --> Destination

InputsDestination就是通过这个上下文来链接起来的。

创建audioContext:

var audioContext = new AudioContext();

OscillatorNode

OscillatorNode(振荡节点): 它能够产生任何频率(frequency)和所有基本波形(wave shapes),比如: sine | sawtooth(锯齿) | triangle | square

1.type

波形type

1.创建一个简单的音频音调

例如:

# 创建一个振荡器
var oscillator = audioContext.createOscillator();
# 选择一种信号波形(waveform shape)  
# 可选的有 sine, sawtooth, triangle, square
oscillator.type = 'sawtooth';

# 连接Destination(扬声器)
oscillator.connect(audioContext.destination);

# currentTime 可读可写, 未设置默认为0
oscillator.start(audioContext.currentTime); // 开始
oscillator.stop(audioContext.currentTime + 2); // 2s后停止

完整代码:

var audioContext = new AudioContext();
var oscillator = audioContext.createOscillator();
oscillator.type = 'square';
oscillator.connect(audioContext.destination);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 2);

2.frequency

振荡器节点有个属性叫 frequency, 单位: Hz(赫兹), 默认为 440Hz
改变音调。

oscillator.frequencyAudioParam实例,大多数Audio Nodes都是AudioParam实例,这个类有很多的属性。

设置频率:

oscillator.frequency.value = 880; // 单位Hz

# 直接设置frequency,错误
oscillator.frequency = 800; // 错误

3.半音阶(Chromatic Scale)

半音阶计算有些技巧,因为频率(frequency)将倍率(octave)(12个半音)翻倍。
(Chromatic note frequencies are slightly tricky to calculate because the frequency doubles every octace(12 semitones) you go up)

计算公式

# noteOffset: 音色偏移
baseFrequency * Math.pow(2, noteOffset / 12)

比如从 middle A 上升7个半音(7 semitones) E, 则计算为:

oscillator.frequency.value = 440 * Math.pow(2, 7 / 12); // 659.255..

再比如,下降14个半音到 G

oscillator.frequency.value = 440 * Math.pow(2, -14 / 12); // 195.998..

一个简单点的计算方式

使用OscillatorNode的 detune(失谐)属性,这个属性允许使用半音的百分之一。

比如使用detune,如果想从 Middle A 上升 7个半音到 E,则可以:

oscillator.detune.value = 700 // noteOffset * 100

注意点

  • 频率与音调(半音阶)之间的关系计算: baseFrequency * Math(2, noteOffset / 12)
  • Middle A 是440Hz, 即振荡器默认的频率
  • Octave指八度音阶, semitones 指音阶, chromatic scale指半音阶
  • 使用detune来转换音频,以100分之一直接设置noteOffset即可

连续播放示例

var ctx = new AudioContext();

function play(delay, pitch, duration) {
  var startTime = ctx.currentTime + delay;
  var endTime = startTime + duration;
  // 定义一个振荡器
  var oscillator = ctx.createOscillator();
  // 定义音色  
  oscillator.frequency.value = 440 * Math.pow(2, pitch / 12);
  // 或者
  // oscillator.detune.value = pitch * 100;


  // 连接destination
  oscillator.connect(ctx.destination);
  // 开始和结束
  oscillator.start(startTime);
  oscillator.end(endTime);
}

// 调用,通过delay产生连续的音频
play(0, 3, 0.5);
play(1, 10, 0.5);
play(2, 15, 0.5);

4.对音频进行过滤:BiquadFilterNode

高通滤波(high-pass filter):即对低频的音色进行过滤,保留高频的音色。

使用 BiquadFilterNode 对音频进行控制, 过滤的类型有 lowpass(默认值) | highpass | bandpass | lowshelf | highshelf | peaking | notch | allpass.

Biquad Filter 字面意思是: 二阶滤波器。

Lowpass

lowpass 过滤是默认的类型,允许低于该频率的信号通过,高频的则过滤掉。

var filter = audioContext.createBiquadFilter();
filter.connect(audioContext.destination);
oscillator.connect(filter);

// 过滤掉所有高于500Hz的音频
filter.type = 'lowpass';
filter.frequency.value = 500;

highpass

highpass指高频的通过,低频的过滤掉

// 低于3000都被过滤
filter.type = 'highpass';
filter.frequency.value = 3000;

bandpass

允许频率有个公差(tolerance), 通过 Q 来指定, Q值越大, frequency越低

filter.type = 'bandpass';
filter.frequency.value = 1000;
filter.Q.value = 1

5.调节音频(modulate filter cutoff)

对于 AudioParam 实例 frequency 有几个方法可以在指定时间内改变音频

setValueAtTime(value, time)

在一个精确的时间设置一个常量更改AudioParam的值,以AudioContext.currentTime来衡量

linearRampToValueAtTime(value, endTime)

线性的改变AudioParam的值

exponentialRampToValueAtTime(value, endTime)

以指数方式该案AudioParam的值

示例:

// 预设频率,避免在起始时就跳动
filter.frequency.value = 200;

// 计划开始时间
filter.frequency.setValueAtTime(200, audioContext.currentTime)

// 变化(ramp)到指定值,在规定时间内
filter.frequency.linearRampToValueAtTime(6000, audioContext.currentTime + 2) // 2s

6.Gain Node 增益效果

使用 GainNode 来改变输出音量

# 创建增益节点
var amp = audioContext.createGain();
# 连接到destination
amp.connect(audioContext.destination);

# 音量减半
amp.gain.value = 0.5

可以使用 setTargetAtTime() 对增益的值进行实时扫描

/*
 * targetValue: 0 | 1, 0表示开始时, 1表示结束时
 * startTime: audioContext.currentTime
 * tiemConstant: 指数衰减率(0 - 1),时间常量,秒为单位
 */
setTargetAtTime(targetValue, startTime, timeConstant)

有两种方式 Attact(开始时柔化声音0-1)Release(在尾部柔化声音1-0)

var startTime = audioContext.currentTime;
amp.gain.value = 0; // 0 - 100
amp.gain.setTargetAtTime(0, startTime, 0.1);

var endTime = startTime + 2;
amp.setTargetAtTime(1, endTime, 0.2)

7.颤音(Vibrato)

在振荡器连接 oscillator.detune 之前放大输出效果

改变失谐(detune)值 在 2Hz时, +/- 100 cents

var vibrato = audioContext.createGain();
vibrato.gain.value = 100;
vibrato.connect(oscillator.detune);

var lfo = audioContext.createOscillator();
lfo.connect(vibrato);
lfo.frequency.value = 2;

lfo.start(audio.currentTime);
lfo.stop(audio.currentTime + 2);

总结

对一些新的API进行了粗略的了解,大多专业名词,但是实现原理比较简单, 输入音频源,经过AudioContext,将各种效果节点连接起来,然后输出音频源

专业词汇比如:

  1. 振荡器(OscillatorNode)
  2. 半音阶使用frequency表示的公式,也可以使用失谐detune表示
  3. 音频过滤器BiquadFilterNode
  4. 增益都节点音量进行调节GainNode, 还可以使用颤音效果, 对特定频率的音色进行波动

其他的一些效果如下:

var audioContext = new AudioContext()
var analyser = audioContext.createAnalyser() // 分析器
var distortion = audioContext.createWaveShaper() // 扭曲器
var gainNode = audioContext.createGain() // 增益 
var convolver = audioContext.createConvolver() // 卷积器
var biquadFilter = audioContext.createBiquadFilter() // 音频过滤器
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • The Audio Listener acts as a microphone-like device. It r...
    Moment__格调阅读 1,837评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 平时吃饭时总是对女儿说,吃饭时不能说话,好好吃饭,吃完饭再说,吃完饭再玩。 今天晚饭的时候,奶奶说了一句:...
    boy118阅读 141评论 1 1
  • 都说你向阳 都说你勇敢 在我无助迷茫的时候 我每每告诉自己要向你一样 因为葵花向阳 因为你充满正能量 却忘了你的花...
    向日葵的梦LI阅读 251评论 0 1