更高效的decodeAudioData()?

Posted

技术标签:

【中文标题】更高效的decodeAudioData()?【英文标题】:More efficient decodeAudioData()? 【发布时间】:2015-11-24 11:56:53 【问题描述】:

我正在使用网络音频 api 将 n 通道音频文件解码为单独的通道,然后将这些通道渲染到画布上以直观地创建频率计。

我正在使用 decodeAudioData 解码字节数组缓冲区,然后分配给单独函数中的音频缓冲区源节点。

 // load the specified sound
function loadSound(url) 
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';

    // When loaded decode the data
    request.onload = function () 

        // decode the data
        context.decodeAudioData(request.response, function (buffer) 
            // when the audio is decoded play the sound
            holdingBuffer = buffer;
            setupSound(buffer);
        , onError);
    
    request.send();

我遇到的问题是,当我尝试解码大约 60mb + 的音频时,由于内存空间不足,浏览器会崩溃。decodeAudioData 函数非常耗内存!

我想知道是否有人对更有效地解码更大的音频文件有任何经验?

【问题讨论】:

您在移动设备上运行吗? 60 MB(压缩)很大,但对于台式机来说不是那么大。 【参考方案1】:

问题是解码音频占用的内存量。只是为了举例,我假设您的 60MB 音频文件是 MP3。

这显然取决于比特率,但假设您的速率为 128kbps——这是相当典型的。这意味着您要加载大约一个小时的立体声音频。

但网络音频 API 解码为 32 位,通常为 44.1 或 48kHz(这取决于您的声卡,据我所知)。

不管怎样,假设是 48kHz 的 32 位。

这意味着每个通道是每秒 32 * 48000 位。即每分钟 32 * 48000 * 60 位,整个小时为 32 * 48000 * 60 * 60 位。当然,我们乘以 2,因为我们假设为立体声。

这意味着总共有 11059200000 位音频数据——这是一个 1.3824GB 的音频缓冲区,需要加载到内存中。所以,基本上 - 这是大量的内存。

这里真的没有简单的答案。您可以尝试在服务器上生成波形/光谱图/任何东西。或者您可以尝试分块加载音频文件,以便您可以单独(串行)处理它们并让它们被垃圾收集。

可能还有其他解决方案,但这是立即想到的两个。

【讨论】:

或使用 MediaElementAudiosource 将 mp3 流式传输到 WebAudio。 是的,如果渲染可以实时发生,那肯定有效。出于某种原因,我认为 OP 正在寻找生成波形,但听起来它实际上是一个频谱图。 无论您在做什么,您都不需要一次在内存中保存整个音频文件。这就是 decodeAudioData API 疯狂的原因。 我认为 Web Audio API 的设计目的更多是为了游戏之类的东西,而不是播放巨大的音乐文件或其他任何东西。我们已经有了 元素。对于游戏中的音效,绝对将整个缓冲区加载到内存中是有意义的,因为声音可能只有 1 或 2 秒长。从磁盘流式传输数据不值得付出额外的努力。

以上是关于更高效的decodeAudioData()?的主要内容,如果未能解决你的问题,请参考以下文章

让 SQL 查询更高效

凌乱的 SQL 查询需要更高效

高效的秘密让k8s运维更高效-日志搜索脚本

高效的秘密让k8s运维更高效-日志搜索脚本

两个 PostgreSQL 索引中哪个更高效?

编程更快速,切削更高效,5轴铣削/铣削车削等