本系列文章主要是介绍 Web Audio API 的相关知识,以及 web语音通信 中会遇到的一些问题,阐述可能存在错误,还请多多斧正!

很多粤语剧都提供了两个声道,一个左声道为粤语,一个右声道有国语。观看者可以自由切换声道,那么切换声道的原理是什么呢?在播放器中,只需要把不同的声道切换到声轨就行了,因为有左右两个声道,所以播放器至少是包含两个声轨的。如果我们想听粤语,只需要将右声道声轨的声音设置为 0,或者临时删掉右声道声轨。本文主要是利用 GainNode 节点控制音量的属性实现两个音轨之间的相互切换,Cross-fading 的意思可以在后面的 DEMO 中用耳朵体会出来~

本文地址:http://www.cnblogs.com/hustskyking/p/webAudio-cross-fading.html,转载请注明源地址。

P.S:请在较新版的 chrome 火狐 Firefox 中测试。

一、两个声音之间的声轨切换

1. 原理介绍

在一个 AudioContext 中可以输入多个音频流,而这些音频流在 AudioContext 这个环境中辗转反侧,最后的出路也就是 DestinationNode:

source 1 ---+

|----> Destination

source 2 ---+

而要实现上面两个声轨的切换,实则是它容易了,我们可以在他们到达 Destination 之前,加一个 GainNode,上文 已经对 GainNode 做了详细的说明,本文就不继续赘述了。

2. DEMO 演示

首先要创建两个音频,平时我们都是使用 audio 节点带上 src 属性,插入到 DOM 中让其自动播放音频,本文将使用其他的方式拿到音频流:

var tank = new Audio("http://qianduannotes.duapp.com/file/tankWar.mp3");

我准备了两个音频,一个是 tankWar.mp3 ,经典的坦克大战开场音乐,另一个是 SuperMario.mp3,超级玛丽的背景音乐,前者稍微短一些,所以在播放的时候将其设定为循环播放:

tank.loop = true;

然后利用 createMediaElementSource 这个函数从 Media 中获取到音频流:

var source1 = context.createMediaElementSource(tank);

过程十分简单,整个 AudioContext 的连接模型为:

source 1 --> GainNode 1 -+

|----> Destination

source 2 --> GainNode 2 -+

然后用同一个控制棒来控制 GainNode 1 和 2。

<input type="range" min="0" max="100" id="volume" />
<script type="text/javascript">
var tank = new Audio("http://qianduannotes.duapp.com/file/tankWar.mp3");
tank.loop = true;
var mario = new Audio("http://qianduannotes.duapp.com/file/SuperMario.mp3");
mario.loop = true; var AudioContext = AudioContext || webkitAudioContext;
var context = new AudioContext();
var source1 = context.createMediaElementSource(tank);
var source2 = context.createMediaElementSource(mario);
var gain1 = context.createGain();
var gain2 = context.createGain();
//连接:source → gain → destination
source1.connect(gain1);
source2.connect(gain2);
gain1.connect(context.destination);
gain2.connect(context.destination);
//音量控制
var value;
onload = volume.onchange = function(){
gain1.gain.value = volume.value / 100;
gain2.gain.value = 1 - volume.value / 100;
}; tank.onload = mario.onlond = function(){
console.log("var1, var2");
}
tank.play();
mario.play(); </script>

代码没有封装,写的稍微有些乱,不过看了之前的说明,应该可以理解这段代码~

3. 效果增强

上面的音量控制,我使用的是线性控制:

gain1.gain.value = volume.value / 100;
gain2.gain.value = 1 - volume.value / 100;

效果并不是特别好,他对音量的控制如下图:

稍微修改下控制函数:

var vol = volume.value / 100;
gain1.gain.value = Math.cos(vol * 0.5 * Math.PI);
gain2.gain.value = Math.cos((1.0 - vol) * 0.5 * Math.PI);

可以感受到音量的变化是这样的:

详情可以戳这个demo:http://qianduannotes.duapp.com/demo/audio/

二、小结

本文的目的是介绍 Web Audio API 的 GainNode 节点的使用,并将此应用到声道的切换之中,上面的例子不能算是严格的声道切换,但如果我们只给 volume 参数设定 0 ,50, 100 这三个值,那效果跟声道的切换就差不多了~

由于这几篇文章都是关于 Node 之间的相互连接,技术含量并不多,主要是读懂 API 以及相关使用方法。行文仓促,如有错误地方,还请斧正!

三、参考资料

[Voice communications] 声道的转换的更多相关文章

  1. [Voice communications] 声音的滤波

    本系列文章主要是介绍 Web Audio API 的相关知识,以及 web语音通信 中会遇到的一些问题,阐述可能存在错误,还请多多斧正! 通过设备获取音频流会不可避免的渗入一些杂音,这些杂音可能来自你 ...

  2. [Voice communications] 音量的控制

    改变音频的音量是音频处理中最基础的部分,我们可以利用 GainNode 来构建 Mixers 的结构块.GainNode 的接口是很简单的: interface GainNode : AudioNod ...

  3. [Voice communications] 看得到的音频流

    上文介绍了 Web Audio API 的相关知识,以及如何在你的 web 程序中引入 音频流,内容都是介绍性的,所以没有写太多 DEMO.本文重点讲解如何利用 Web Audio API 中的中间节 ...

  4. [Voice communications] 让音乐响起来

    本系列文章主要是介绍 Web Audio API 的相关知识,由于该技术还处在 web 草案阶段(很多标准被提出来,至于取舍需要等待稳定版文档来确定,草案阶段的文档很多都会被再次编辑甚至重写.全部删除 ...

  5. (Step by Step)How to setup IP Phone Server(VoIP Server) for free.

    You must have heard about IP Phone and SIP (Software IP Phone).Nowadays standard PSTN phone are bein ...

  6. Unity声音-音源组件

    音源组件(AudioSource) 音源是场景中在某个位置的发声装置,好像一个喇叭.它播放着音频片段 (Audio Clip). 发出的声音将输出到声音监听器(audio listener),或者声音 ...

  7. 每日英语:5 Things to Know About Missing Malaysia Airlines Flight and Air Safety

    Malaysia Airlines Flight MH370, with 239 people aboard, lost contact early Saturday with the airline ...

  8. XAudio2学习之调节音调

    频率比有两个地方能够设置.一个是在创建IXAudio2SourceVoice对象的时候.一个是调用IXAudio2SourceVoice::SetFrequencyRatio来调节. 在创建IXAud ...

  9. 转载:P2P技术原理及应用(1)

    转帖allen303allen的空间 作 者:金海 廖小飞 摘要:对等网络(P2P)有3种主要的组织结构:分布式哈希表(DHT)结构.树形结构.网状结构.P2P技术已 经延伸到几乎所有的网络应用领域, ...

随机推荐

  1. 数据库连接池c3p0学习

    这里只记录c3p0的数据源,不会涉及到其它方面和别的数据库连接池的对比 配置文件主要的实现方式有三种: 1.手写代码去加载一个配置文件 创建一个config.properties文件如下: drive ...

  2. js 倒计时

    /** * 启动,秒杀倒计时. time格式:DDHH24MISS 例如: time="11223344"; * */function timer(time) { var d = ...

  3. 使用WCF 创建 Rest service

    REST SERVICE 允许客户端修改url路径,并且web端功过url 请求数据. 他使用http协议进行通讯,想必大家都知道 . 并且我们可以通过设置进行数据类型转换, 支持XML,JSON 格 ...

  4. vue2.0有哪些变化

    vue2.0之后有哪些变化: 1.每个组件模板template,不再支持片段代码 之前: <template> <h3>vue-router+vue-loader</h3 ...

  5. 收集常用的.net开源项目

    Json.NET http://json.codeplex.com/ Json.NET是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过Lin ...

  6. mysql优化笔记之分页

    过年闲得蛋疼,于是看看mysql优化,看了网上好多关于分页的优化方法,但是呢,我亲自试上一把的时候,没有出现他们说的现象...难道是我的机器问题么? 下面看看我的实践记录,希望看到的加入进来交流一下O ...

  7. Hdu4311 || 4312Meeting point-1/-2 n个点中任意选一个点使得其余点到该点曼哈顿距离之和最小

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...

  8. 【MongoDB初识】-其他操作

    又发现一种查询写法$wheredb.class.find({$}}) 排重db.class.distinct("stuCount") 一.MapReduce(摘录MongoDB实战 ...

  9. 2019年台积电进军AR芯片,将用于下一代iPhone

    近日,有报道表示台积电10nm 芯片可怜的收益率可能会对 2017 年多款高端移动设备的推出产生较大的影响,其中自然包括下一代 iPhone 和 iPad 机型.不过,台积电正式驳斥了这一说法,表明1 ...

  10. 线程和线程池的理解与java简单例子

    1.线程 (1)理解,线程是系统分配处理器时间资源的基本单元也是系统调用的基本单位,简单理解就是一个或多个线程组成了一个进程,进程就像爸爸,线程就像儿子,有时候爸爸一个人干不了活就生了几个儿子干活,会 ...