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

Why does this decrease the audio quality?

我在 Flask 应用程序中将音频从客户端流式传输到服务器,但接收到的音频质量很差。

在客户端,我对音频缓冲区进行了如下预处理:

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;
}

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

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)

但生成的音频听起来金属味、断断续续且嘈杂。生成的波形如下所示:

我的代码中哪里的音频质量丢失了?如何在不损失质量的情况下流式传输音频?

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

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

然后在服务器端对每个样本进行另一个循环,只是为了将样本放入列表中(数据不是已经以列表的形式出现了吗?)。然后才将该列表打包成二进制数组,然后写入磁盘。

仅仅写一个缓冲区就需要大量工作,您可能正在丢失数据。

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

一旦您获得原始的 float32 数据,如果您需要另一种格式的数据,您可以查看添加转换(希望只在一个地方)是否仍然允许您维持实时。我怀疑您可能需要在 C/C++ 中编写此转换代码,因为 Python 对于此类事情来说太慢了。如果您正沿着这条路走下去,研究 Cython 可能是个好主意。