为什么这会降低音频质量?

use*_*461 5 javascript audio pack flask flask-socketio

我正在将烧录应用程序中的音频从客户端传输到服务器,但收到的音频质量非常低.

在客户端,我按如下方式预处理音频缓冲区:

this.node.onaudioprocess = function(e){
      var buf = e.inputBuffer.getChannelData(0);
      var out = new Int16Array(buf.length);
      for (var i = 0; i < buf.length; i++){
        var s = Math.max(-1, Math.min(1, buf[i]));
        out[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
      }
      socket.emit('audio event',{data: out})
      return;
}
Run Code Online (Sandbox Code Playgroud)

在服务器端,我收到如下音频:

audio_file = open('tempfile.raw', 'w')

@socketio.on('audio event')
def audio_message(message):
    dat = [v[1] for v in sorted(message['data'].iteritems())]
    n = len(dat)
    byteval = struct.pack('<'+str(n)+'h',*dat)
    audio_file.write(byteval)
Run Code Online (Sandbox Code Playgroud)

但由此产生的音频听起来很金属,中断和嘈杂.以下是结果波形的外观:

收到波浪样本

在我的代码中,音频质量丢失了吗?如何在没有质量损失的情况下传输音频?

Mig*_*uel 2

我对音频处理方式的第一印象是实时处理速度太慢。

在客户端上,您迭代每个样本,应用边界检查(您真的需要这样做吗?),然后对每个样本应用条件和乘法,将 float32 转换为 int16 格式。

然后在服务器端,您对每个样本进行另一个循环,只是为了将样本放入列表中(数据不是已经作为列表发送给您了吗?)。然后,您才能将该列表打包到二进制数组中,然后写入磁盘。

仅写入缓冲区就需要大量工作,您可能会丢失数据。

我建议您尝试以下操作:删除所有转换,然后查看是否可以以本机 float32 格式获取流经系统的数据。使用socket.io,您可以直接从客户端发送打包的 float32 数据。还没有对此进行测试,但我相信socket.emit('audio event',{data: buf.buffer})会直接发送二进制有效负载,并且无需客户端转换。然后在服务器上,message['data']将是一个可以直接写入磁盘的二进制有效负载。要检查数据看起来是否良好,您可以使用 audacity,使用“导入原始数据”对话框中的 32 位浮点选项。

一旦原始 float32 数据正常工作,如果您需要另一种格式的数据,您可以查看添加转换(希望仅在一个位置)是否仍然允许您维持实时性。我怀疑您可能需要用 C/C++ 编写此转换代码,因为 Python 对于此类事情来说太慢了。如果您打算走这条路,研究Cython可能是个好主意。