2016-09-02 40 views
5

我在我的烧瓶应用程序中将音频从客户端传输到服务器,但收到的音频质量很差。这为什么会降低音频质量?

在客户端,我预处理音频缓冲器如下:

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) 

但得到的音频声音的金属,中断和嘈杂。以下是得到的波形的样子:

received wave sample

凡在我的代码在音频质量失去了什么?如何在没有质量损失的情况下传输音频?

回答

2

我对你如何处理音频的第一印象是它实时工作太慢。

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

然后在服务器端,通过每个样本做了另一个循环,只是为了将样本放入一个列表中(不是已经以列表形式发送给您的数据?)。然后才把这个列表打包成写入磁盘的二进制数组。

这只是写了一个缓冲区很多工作,你可能会丢失数据。

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

一旦你得到原始float32数据的工作,如果你需要另一种格式的数据,你可以看到是否添加一个转换(希望只在一个地方)仍然允许你保持实时。我怀疑你可能需要在C/C++中编写这种转换,因为对于这种类型的Python来说太慢了。如果你正在走这条路,那么看看Cython可能是个好主意。

+0

buf.buffer中发生了什么样的转换?这是否将float32array转换为二进制缓冲区? – user2212461

+0

不,“缓冲区”属性返回数组的底层二进制结构,不进行任何转换。请参阅JavaScript类型数组的文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays。 – Miguel