2016-09-02 28 views
5

Tôi đang phát âm thanh trong ứng dụng bình của mình từ máy khách đến máy chủ, nhưng âm thanh nhận được có chất lượng rất thấp.Tại sao điều này làm giảm chất lượng âm thanh?

Trên client, tôi preprocess bộ đệm âm thanh như sau:

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

Về phía server, tôi nhận được âm thanh như sau:

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) 

Nhưng âm thanh dẫn âm thanh kim loại, bị gián đoạn và ồn ào. Đây là cách các dạng sóng kết quả trông:

received wave sample

đâu trong mã của tôi là chất lượng âm thanh bị mất? Làm cách nào để phát trực tuyến âm thanh mà không bị mất chất lượng?

Trả lời

2

Ấn tượng đầu tiên của tôi về cách bạn xử lý âm thanh là quá chậm để hoạt động trong thời gian thực. Trên máy khách, bạn lặp qua từng mẫu, áp dụng kiểm tra giới hạn (bạn có thực sự cần phải làm điều đó không?) Sau đó chuyển từ float32 sang định dạng int16 áp dụng điều kiện và phép nhân cho từng mẫu riêng lẻ.

Sau đó, ở phía máy chủ, bạn thực hiện một vòng lặp khác qua từng mẫu, chỉ để lấy mẫu vào danh sách (không phải là dữ liệu đã đến với bạn dưới dạng danh sách?). Và chỉ sau đó bạn đóng gói danh sách đó thành một mảng nhị phân được ghi vào đĩa.

Đây là rất nhiều công việc để chỉ viết bộ đệm, có thể bạn đang mất dữ liệu.

Dưới đây là những gì tôi khuyên bạn nên thử: xóa tất cả chuyển đổi và xem liệu bạn có thể lấy dữ liệu được truyền qua hệ thống ở định dạng float32 gốc hay không. Với socket.io bạn có thể gửi dữ liệu float32 được đóng gói trực tiếp từ máy khách. Chưa thử nghiệm điều này, nhưng tôi tin rằng socket.emit('audio event',{data: buf.buffer}) sẽ nhận được tải trọng nhị phân được gửi trực tiếp và không có chuyển đổi phía máy khách. Sau đó trên máy chủ, message['data'] sẽ là một tải trọng nhị phân mà bạn có thể ghi trực tiếp vào đĩa. Để kiểm tra xem dữ liệu có tốt hay không, bạn có thể sử dụng tính năng audacity, sử dụng tùy chọn nổi 32 bit trong hộp thoại Nhập liệu.

Khi bạn nhận dữ liệu float32 thực, nếu bạn cần dữ liệu ở định dạng khác, bạn có thể xem thêm một chuyển đổi (hy vọng chỉ ở một nơi) vẫn cho phép bạn duy trì thời gian thực. Tôi nghi ngờ bạn có thể cần phải mã chuyển đổi này trong C/C++, vì Python là quá chậm đối với loại điều này. Nếu bạn đang đi xuống con đường này, nhìn vào Cython có thể là một ý tưởng tốt.

+0

Loại chuyển đổi nào xảy ra trong buf.buffer? Điều đó có chuyển đổi float32array thành một bộ đệm nhị phân không? – user2212461

+0

Không, thuộc tính 'buffer' trả về cấu trúc nhị phân cơ bản của mảng, không có bất kỳ chuyển đổi nào. Xem tài liệu về các mảng được nhập JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays. – Miguel

Các vấn đề liên quan