网络音频API:音乐感知调度和动态循环(2016)

2020-05-02 18:06:43

我最近第一次玩网络音频API,所以我想我应该把我学到的东西写下来。我想那是我的工作什么的。

我们可以用网络音频做的最简单的事情就是播放声音。但是要做到这一点,我们首先需要加载和解码一些东西:

//上下文连接到设备扬声器。//每个文档只需要其中一个。const context=new AudioContext();//获取文件FETCH(';sound.mp4';)//将其作为arrayBuffer读取到内存中。则(RESPONSE=>;RESPONSE。arrayBuffer())//将其从mp3/aac/任意格式转换为原始音频数据。则(arrayBuffer=>;Context。decdeAudioData(ArrayBuffer))。然后(audioBuffer=>;{//现在我们准备好玩了!});

不幸的是,我们需要在Safari中解决一些问题。我们需要使用webkitAudioContext-Safari不支持无前缀版本。它还不支持FETCH(它还在开发中),所以我们需要使用XHR)。而且decdeAudioData不支持承诺,所以我们需要多填。

//创建source://表示播放头部。常量来源=上下文。createBufferSource();//给它我们加载的音频数据:source。Buffer=audioBuffer;//插入OUTPUT:SOURCE。连接(上下文。目的地);//我们出发了!消息来源。Start();

所以,是的,它比仅仅使用音频…复杂得多。";>;播放声音,但Web音频可以做的更多。网络音频的控制量给你带来了很大的乐趣,但也有点令人望而生畏。在这篇文章中,我只是触及皮毛,看看如何循环和排列声音。

我们试图让它尽可能地滑稽可笑,而音乐是其中很大的一部分。音乐是由Plan8制作的,他们只花了一天的时间创作(我们误读了我们要使用的一段音乐的许可证,所以截止日期是我们的错。不管怎么说,他们做的音乐要好得多)。他们也有用于安排音频的JS库,但是嘿,我有一些拖沓的心情,所以我自己做了。

大型网络测验中的音乐有三个阶段,我们希望在提问时在这三个阶段之间切换。使用上面的代码,我加载了三个缓冲区,phase1AudioBuffer、phase2AudioBuffer和staAudioBuffer,每个缓冲区代表Big Web Quiz音乐的不同阶段。

一个简单的解决方案是先播放阶段1,然后停止播放阶段2:

const phase1Source=上下文。createBufferSource();phase1Source。Buffer=phase1AudioBuffer;phase1Source。连接(上下文。目标);阶段1Source。Start();//稍后…。const phase2Source=上下文。createBufferSource();phase2Source。Buffer=phase2AudioBuffer;phase2Source。连接(上下文。Destination);//停止阶段1阶段1Source。stop();//启动第二阶段phase2Source。Start();

即使我们已经将音频数据加载到内存中,在我们调用start()和实际播放音频之间仍然存在差距。

如果您希望声音尽快播放,并且不介意声音是否在几毫秒外播放,比如玩家收集硬币时在游戏中播放声音,这是可以的,但是当同步两个剪辑时,事情需要精确。

要对音频做任何精确的操作,您需要提前安排时间。Start和Stop都有一个可选的数字,即实际开始/停止的时间,而context.currentTime提供了与音频上下文相关的当前时间。

你需要提前通知多少取决于硬件,但克里斯·威尔逊(Chris Wilson)可靠地告诉我,四分之一秒是超级安全的,即使对于速度较慢的硬件也是如此。

四分之一秒是一个很长的延迟,但在这种情况下,同步对我们来说比即时性更重要。

注意:在web音频API中,时间以秒为单位,而大多数其他web API使用毫秒。

将音频编码成MP3或AAC这样的格式是一个有损的过程,但你至少可以选择编码器。当你使用decdeAudioData时,你会依赖于浏览器使用的任何解码器,这可能会让人震惊,但有时不同的浏览器会有不同的做法。

原始视频的开头/结尾是无缝的,但如果你使用的是Chrome稳定版、火狐版或Edge版,你会看到一个巨大的差距。我说的巨大是指45毫秒,但你知道,当我们试图在两个片段之间立即切换时,这是一个很大的问题。

在Chrome Canary中,这一差距几乎消失了。而Safari则恰到好处,完全没有差距。

在本文的初稿中,我祝贺Safari做得很好,但是来自Mozilla的实际专家Paul Adenot向我扔了几个知识炸弹(当然是以友好的方式)。

开始处的间隙由编码器指定为元数据。摘自苹果公司的文档:

…。编码器在第一个“真实”音频样本之前添加至少1024个静音样本,通常还会添加更多。这是