前言

想在网页中实现实时音频变声效果该如何实现呢,之前遇到这种处理音视频的需求,可能会想到需要借助C代码实现。但是现在随着浏览器性能的提升、web API的丰富,通过浏览器原生的API也可以操作音频数据实现很多复杂的效果,为web音频开发提供了更多的选择。下面介绍几种采用原生Web Audio API实现变声效果的过程中尝试的几种方案,感兴趣的同学一起来了解下吧。

说明:本文讨论范围为变声场景中的变速变调方案,有其它两种场景:变速不变调、变调不变速需求的同学请移步参考链接或其它方案

Web Audio API介绍

开始之前先简单了解下Web Audio APIWeb Audio API提供了一组在web上操作音频的API,可以使开发者自选音频数据来源,为音频添加效果,使声音可视化,为声音添加空间效果等功能。音频的输入流可以理解为一组buffer,来源可以是读取音频文件产生到内存中的AudioBufferSourceNode,也可以是来自HTML中audio标签的MediaElementAudioSourceNode,也可以是来自音频流(例如麦克风)的MediaStreamAudioSourceNode。例如,采集自己设备上的麦克风声音连接到扬声器:

// 创建音频上下文
const audioContext = new AudioContext();
// 获取设备麦克风流
stream = await navigator.mediaDevices.getUserMedia({ audio: true}).catch(function (error) {console.log(error);});
// 创建来自麦克风的流的声音源
const sourceNode = audioContext.createMediaStreamSource(stream);
// 将声音连接的扬声器
sourceNode.connect(audioContext.destination);

就可以对着麦克风说话听到自己的声音了。对上述来源数据流的处理被设计成一个个的节点(Node),具有模块化路由的特点,需要添加什么样的效果添加什么样的node,例如一个最常见的操作是通过把输入的采样数据放大来达到扩音器的作用(GainNode),示例代码:

// 创建音频上下文
const audioContext = new AudioContext();
// 创建一个增益Node
const gainNode = audioCtx.createGain();
// 获取设备麦克风流
stream = await navigator.mediaDevices.getUserMedia({ audio: true}).catch(function (error) {console.log(error);});
// 创建来自麦克风的流的声音源
const sourceNode = audioContext.createMediaStreamSource(stream);
// 将声音经过gainNode处理
sourceNode.connect(gainNode);
// 将声音连接的扬声器
gainNode.connect(audioContext.destination);
// 设置声音增益,放大声音
gainNode.gain.value = 2.0;

以上只是连接了声音放大的node,如果想要增加其它效果,可以继续往上添加node连接connect,例如滤波器(BiquadFilterNode)、立体声控制(StereoPannerNode)、对信号进行扭曲(WaveShaperNode)等等。这种模块化设计提供了灵活的创建动态效果和复合音频的方法,是不是有种变魔法的感觉,哪里修改点哪里(添加Node)非常方便。例如,以下展示了一个利用 AudioContext 创建四项滤波器节点(Biquad filter node)的例子:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();// 创建多个不同作用功能的node节点
var analyser = audioCtx.createAnalyser();
var distortion = audioCtx.createWaveShaper();
var gainNode = audioCtx.createGain();
var biquadFilter = audioCtx.createBiquadFilter();
var convolver = audioCtx.createConvolver();// 将所有节点连接在一起source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.connect(distortion);
distortion.connect(biquadFilter);
biquadFilter.connect(convolver);
convolver.connect(gainNode);
gainNode.connect(audioCtx.destination);// 控制双二阶滤波器biquadFilter.type = "lowshelf";
biquadFilter.frequency.value = 1000;
biquadFilter.gain.value = 25;

可以看到为声音流添加处理效果就像穿项链一样,一个接一个,最后得到最终效果,实现效果可以参考官方样例voice-change-o-matic。一个简单而典型的 web audio 流程如下:

  1. 创建音频上下文

  2. 在音频上下文里创建源 — 例如, 振荡器,流

  3. 创建效果节点,例如混响、双二阶滤波器、平移、压缩

  4. 为音频选择一个目的地,例如你的系统扬声器

  5. 连接源到效果器,对目的地进行效果输出

变声效果实现

首先回顾一下声音的基础知识,声音是由物体振动产生的机械波,常接触到的有以下三个特性:

  • 频率:频率越大,音调越高;频率越小,音调越低。

  • 振幅:振幅越大,音量(响度)越大;振幅越小,音量越小。

  • 音色:即波形,听声辨人的主要依据

这里说的变声效果是改变声音的音调,变声效果根据不同的场景可以分为变速不变调、变调不变速以及变调又变速 3 种。变速是指把一个语音在时域上拉长或缩短,而声音的采样率、基频以及共振峰都没有发生变化。变调是指把语音的基因频率降低或升高,共振峰做出相应的改变,采样频率不变。各种方案应用场景如下:

  1. 变速不变调:各种各样的视频播放器中的 2 倍速,0.5 倍速播放就是应用的语音变速不变调原理;当然变速不变调还应用于网络电话 VOIP 中的应对网络抖动,简单的说,就是当网络不好的时候,播放端从网络中拉取到的数据少,缓存区的数据不够用,这个时候就使用缓存的数据播放的慢一点。反之,缓存区数据过多,就播放的快一点。这部分的实现可以参照 webrtc 的 netEQ 模块。平时在使用微信语音的时候应该能感受到网络特别卡时,为了保持语音连续,会故意慢放语音。

  2. 变调不变速:变调不变速主要应用在声效上,声音提高音调将男声变成女生,或则将女生变成男声;另外,变调不变速配合其他一些音效算法,如 EQ,混响,tremolo 和 vibrato 可以实现变声效果,比如 QQ 上的萝莉音,大叔音等。

  3. 变速变调:改变声音播放速率情况下,音调音色也会随着改变,例如玩过磁带的都知道,按快进功能会使声音变尖提高音调,慢放功能使声音变粗,降低音调。

前两种实现都要求对声音知识领域有更深的了解,声音时域、频域,信号的傅里叶变换变化都要去重新去复习一下,学习成本比较高,这里使用第3种方式,比较好接入。要改变声音的播放速率,Web Audio API中提供了AudioBufferSourceNodeplaybackRate属性,可以设置音频的播放速率,使用音频上下文AudioContext.createBufferSource获得实例,示例代码如下:

const play = ()=> {const audioSrc = ref("src/assets/sample_orig.mp3")const url = audioSrc.valueconst request = new XMLHttpRequest()request.open('GET', url, true)request.responseType = 'arraybuffer'request.onload = function() {const audioData = request.responseconst audioCtx = new (window.AudioContext || window.webkitAudioContext)();audioCtx.decodeAudioData(audioData, (audioBuffer) => {let source = audioCtx.createBufferSource();source.buffer = audioBuffer;// 改变声音播放速率,2倍播放source.playbackRate.value = 2;source.connect(audioCtx.destination);source.start(0);});}request.send()
}

可以调整source.playbackRate.value的值来改变音调,大于1提高音调,小于1降低音调。

虽然实现了变声效果,但是这种方式只适合播放音频文件,或者能获取到完整音频流的情况,对于获取麦克风这种持续输入的声音流并不适用,类似的还有SoundTouchJS,它是某大佬实现的SoundTouch的JS版本,使用也是要获取完整音频的数据流,作者也做了相应的解释,参考链接如何处理麦克风获取的实时音频流呢,这里可以借助Web Audio API中的ScriptProcessorNode,它允许使用 JavaScript 生成、处理、分析音频。处理流程图如下:利用它将实时音频流数据处理一下,得到慢放或加速的声音流数据。示例代码如下:

const audioprocess = async () => {const audioContext = new AudioContext();// 采集麦克风输入声音流let stream = await navigator.mediaDevices.getUserMedia({ audio: true}).catch(function (error) {console.log(error);});const sourceNode = audioContext.createMediaStreamSource(stream);const processor = audioContext.createScriptProcessor(4096, 1, 1);processor.onaudioprocess = async event => {// 处理回调中拿到输入声音数据const inputBuffer = event.inputBuffer;// 创建新的输出源const outputSource = audioContext.createMediaStreamDestination();const audioBuffer = audioContext.createBufferSource();audioBuffer.buffer = inputBuffer;// 设置声音加粗,慢放0.7倍audioBuffer.playbackRate.value = 0.7audioBuffer.connect(outputSource);audioBuffer.start();// 返回新的 MediaStreamconst newStream = outputSource.stream;const node = audioContext.createMediaStreamSource(newStream)// 连接到扬声器播放node.connect(audioContext.destination)};// 添加处理节点sourceNode.connect(processor);processor.connect(audioContext.destination)
}

另外,还有一个利用Google开源jungle实现的改变音调的库,并且还有各种混响效果,音频可视化等炫酷功能,也是使用的Web Audio API实现,github链接地址放在这里了,有兴趣也可以体验下,画面长这样

总结

以上就是对Web Audio API的简单介绍和使用的分析,以及采用Web Audio API实现声音简单变声效果的几种实现,大家有哪些更好的实现方案欢迎评论区一起交流!

参考

https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API

https://github.com/cwilso/Audio-Input-Effects

https://mdn.github.io/voice-change-o-matic/

https://github.com/cutterbl/SoundTouchJS

https://cloud.tencent.com/developer/news/818606

https://zhuanlan.zhihu.com/p/110278983

https://www.nxrte.com/jishu/3146.html

- END -

关于奇舞团

奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

Web Audio API实现简单变声效果相关推荐

  1. 如何使用Web Audio API听到“ Yanny”和“ Laurel”的声音

    by _haochuan 通过_haochuan 如何使用Web Audio API听到" Yanny"和" Laurel"的声音 (How you can h ...

  2. 利用HTML5 Web Audio API给网页JS交互增加声音

    转自张鑫旭老师博客 原文地址 一.庞然的HTML5 Web Audio API 首先务必要弄清这一点,本文这里所说的HTML5 Web Audio API和HTML5 元素完全不是一个东西,其体量也完 ...

  3. Web Audio API之手把手教你用web api处理声音信号:可视化音乐demo

    1.Web Audio API 介绍 Web Audio API 提供了在Web上控制音频的一个非常有效通用的系统 ,这些通用系统通俗的讲就是我们可以利用Web Audio API提供的各种方法操作各 ...

  4. web audio api_带有Web Audio API的动态声音

    web audio api This article is part of a web dev series from Microsoft. Thank you for supporting the ...

  5. 【Web】1326- 深入浅出 Web Audio API

    前言 2011被提出,同年草案被Google Chrome和Mozilla Firefox实现 在此之前Web音频较为原始,无法应付较为复杂的应用场景,例如Web游戏或互动应用 旨在提供全套Web音频 ...

  6. HTML 利用 Web Audio API 进行音频可视化

    利用Web Audio API 进行音乐可视化 1.什么是 Web Audio API: 官方:Web Audio API 提供了在Web上控制音频的一个非常有效通用的系统,允许开发者来自选音频源,对 ...

  7. HTML5 Web Audio Api-2 发声oscillator

    (Web Audio Api基础信息整理中,到时候补上) oscillator的意思是振荡器,众所周知,声音就是物体振动产生的声波. 在Web Audio Api中,官方给我们提供了一个振荡器 需要用 ...

  8. ASP.NET Core环境Web Audio API+SingalR+微软语音服务实现web实时语音识别

    处于项目需要,我研究了一下web端的语音识别实现.目前市场上语音服务已经非常成熟了,国内的科大讯飞或是国外的微软在这块都可以提供足够优质的服务,对于我们工程应用来说只需要花钱调用接口就行了,难点在于整 ...

  9. webrtc 语音流java_Web语音处理 - Web Audio API WebRTC

    概述 很多设备都具备native的语音输入功能,并提供App来提供语言录入等功能.如果你想开发一些语言应用,那么针对不同的设备平台,包括desktop和移动设备如ios.android,你可能需要使用 ...

最新文章

  1. python email模块详解_python模块之email: 电子邮件编码解码 (一、解码邮件)-阿里云开发者社区...
  2. Google提出新型学习范式「Deep Memory」,或将彻底改变机器学习领域
  3. Net设计模式实例之解释器模式(Interpreter Pattern)
  4. 如何隐藏system函数的窗口
  5. dropout理解(一)
  6. excel多个工作表求和案例
  7. all any 或 此运算符后面必须跟_用 ANY、SOME 或 ALL 修改的比较运算符
  8. 容器技术之二.Docker的安装和常见问题
  9. 填坑-十万个为什么?(13)
  10. Jsp中使用数据库连接池
  11. BZOJ 3304: [Shoi2005]带限制的最长公共子序列( LCS )
  12. Numeral.js 是一个用于格式化和数字四则运算的js 库
  13. 14.软件架构设计:大型网站技术架构与业务架构融合之道 --- 业务架构思维
  14. vim 树形目录插件NERDTree安装
  15. matlab2016b版本安装
  16. 一键进入高通9008模式_想闯中国智能汽车的高通和想花200亿的威马
  17. 嗨,你真的懂this吗?bianji
  18. python123期末四题编程题 -无空隙回声输出-文件关键行数-字典翻转输出-《沉默的羔羊》之最多单词
  19. c语言用函数写大小写转换,C语言实现大小写转换的三种方法
  20. Android toolchain - develop for Android devices

热门文章

  1. 百度下架PLATO了
  2. 反向传播与梯度下降详解
  3. 【SRE笔记 2022.9.59.6 linux文件系统及软件安装命令】
  4. c语言求余数 fmod,【总结】C/C++取余操作:%、fmod()、remainder()的区别和联系
  5. 【案例】FFMPEG GIF音乐搞笑视频自动生成 内含视频体验
  6. 力扣516:最长回文子序列
  7. pngquant——一个好用的png压缩工具
  8. 主板机入门指南 三星S10+
  9. 行业研究——信创行业
  10. JS:c标签if的使用