[Voice communications] 声道的转换
本系列文章主要是介绍 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 以及相关使用方法。行文仓促,如有错误地方,还请斧正!
三、参考资料
- http://www.w3.org/TR/webaudio/ W3C Group
- http://www.web-tinker.com/ 次碳酸钴
[Voice communications] 声道的转换的更多相关文章
- [Voice communications] 声音的滤波
本系列文章主要是介绍 Web Audio API 的相关知识,以及 web语音通信 中会遇到的一些问题,阐述可能存在错误,还请多多斧正! 通过设备获取音频流会不可避免的渗入一些杂音,这些杂音可能来自你 ...
- [Voice communications] 音量的控制
改变音频的音量是音频处理中最基础的部分,我们可以利用 GainNode 来构建 Mixers 的结构块.GainNode 的接口是很简单的: interface GainNode : AudioNod ...
- [Voice communications] 看得到的音频流
上文介绍了 Web Audio API 的相关知识,以及如何在你的 web 程序中引入 音频流,内容都是介绍性的,所以没有写太多 DEMO.本文重点讲解如何利用 Web Audio API 中的中间节 ...
- [Voice communications] 让音乐响起来
本系列文章主要是介绍 Web Audio API 的相关知识,由于该技术还处在 web 草案阶段(很多标准被提出来,至于取舍需要等待稳定版文档来确定,草案阶段的文档很多都会被再次编辑甚至重写.全部删除 ...
- (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 ...
- Unity声音-音源组件
音源组件(AudioSource) 音源是场景中在某个位置的发声装置,好像一个喇叭.它播放着音频片段 (Audio Clip). 发出的声音将输出到声音监听器(audio listener),或者声音 ...
- 每日英语: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 ...
- XAudio2学习之调节音调
频率比有两个地方能够设置.一个是在创建IXAudio2SourceVoice对象的时候.一个是调用IXAudio2SourceVoice::SetFrequencyRatio来调节. 在创建IXAud ...
- 转载:P2P技术原理及应用(1)
转帖allen303allen的空间 作 者:金海 廖小飞 摘要:对等网络(P2P)有3种主要的组织结构:分布式哈希表(DHT)结构.树形结构.网状结构.P2P技术已 经延伸到几乎所有的网络应用领域, ...
随机推荐
- [MS SQL Server]SQL Server如何开启远程访问
在日常工作中,经常需要连接到远程的MS SQL Server数据库中.当然也经常会出现下面的连接错误. 解决方法: 1. 设置数据库允许远程连接,数据库实例名-->右键--->属性---C ...
- Jquery判断变量是否为空
var aaa=''; if(aaa) { //aaa不为空也不是不可识别对象时执行 } else { //aaa为空或不可识别时执行 } aaa必须是变量,对象的属性好像是不行,
- 【学习篇:他山之石,把玉攻】jquery实现调用webservice
1.webservice端 using System; using System.Collections.Generic; using System.Web; using System.Web.Ser ...
- CozyRSS开发记录12-MVVM,绑定RSS源和数据
CozyRSS开发记录12-MVVM,绑定RSS源和数据 1.引入MvvmLight MVVM最近貌似在前端那块也挺火的.据说,WPF的程序如果不用MVVM,那跟MFC和winform的,也没啥区别. ...
- CURL 模拟http提交
1:CURL模拟get提交 private function httpGet($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_RETUR ...
- sqlmap 帮助信息
Usage: sqlmap.py [options] 选项: -h, --help 显示基本的帮助信息并退出 -hh 显示高级的帮助信息并退出 --version 显示程序版本号并退出 -v VERB ...
- CentOS安装JDK和安装Glassfish
1.首先下载对应CentOS版本的jdk:下载:jdk-7u75-linux-x64.tar.gz 2.下载该jdk到本地,并上传到CentOS系统的opt临时目录下 3.在安装自己下载的jdk之前, ...
- Git 创建本地仓库
前面已经搭好环境了,现在我们缺的是一个管理版本控制的仓库.这次的实验是在电脑本地创建本地仓库.指定路径 默认的位置是在你所安装Git的目录下.Git的仓库你可以建在你电脑的任何目录下(最好不要包含有中 ...
- Linux 用户添加sudo 权限
编辑/etc/sudoers 搜索root 添加 账号 ALL=(ALL) ALL
- 一个快速排序(分类)及使用类似思想实现选择问题[c++实现]
一.快速排序(快速分类)算法: 问题描述:给定线性集中n个元素和一个整数k,1<=k<=n,要求找出这n个元素中第k小的元素. 思想:选取数组A中的某个元素 t=A[s],然后将其他元素重 ...