网络音频API - 实时流在块之间点击。

问题描述:

我正在尝试通过一个node.js(express)服务器上的websocket将音频流式传输到Web浏览器。音频来自iOS设备,是以4k采样的16位单声道wav文件(每秒4000个采样点)。网络音频API - 实时流在块之间点击。

这里是我的代码:

服务器代码:

webSocketServer.on('connection', function connection(client) { 
    client.on('message', function(message) { 
    webSocketServer.clients.forEach(function each(connection) { 
     connection.send(message, { binary: true } 
    ); 
    }); 
}); 

客户端代码:

webSocket = new WebSocket('ws://' + window.location.hostname + ':8080/'); 
webSocket.binaryType = 'arraybuffer' 
webSocket.onmessage = function(message) { 
    var arrayBuffer = message.data // wav from server, as arraybuffer 
    var source = audioContext.createBufferSource(); 
    audioContext.decodeAudioData(arrayBuffer, function(buffer){ 
    source.buffer = buffer 
    source.connect(audioContext.destination) 
    source.start(time); 
    time += source.buffer.duration 
    }, function(){ 
    console.log('error') 
    }) 
}; 

decodeAudioData()似乎是工作,但它返回的音频缓冲器半我是长期待。 (例如,4000个样本只会给我0.5秒的音频,我原本以为这是因为wav是16位而不是32,但切换到32导致decodeAudioData()触发它的错误回调。添加到成功回调:

source.playbackRate.value = 0.5 // play at half speed 
time += source.buffer.duration * 2 // double duration 

这得到定时工作完美,但我留下了一个问题:有一个听得见的“咔嗒”或音频数据块之间的“流行”间隔出后。大约一秒(time += (source.buffer.duration * 2) + 1),我能够发现点击发生在每个块的最开始处。

所以我的主要两个头部划痕是:

1)为什么解码音频播放速度是我所期望的两倍?对于Web Audio API,我的采样率是否过低?为什么我无法解码32位wav?

2)我对数字音频工作站(ableton,逻辑)有一些经验,我知道如果一个波从样本回落到零或反之亦然(即:开始/结束一个正弦波在一个阶段中)。这是怎么回事?有没有办法解决这个问题?将每个单独的样本交叉淡化似乎很愚蠢。为什么每个组块拾取的最后一个都没有停止?

1)我收到的音频实际上是在2k的错误,但wav头仍然说4k,因此双倍速度的错误。

2)见Chris Wilsons answer here最后一段:

最后 - 这是行不通的好,如果声音流不匹配默认音频设备的采样率;总会有点击,因为decodeAudioData将重新采样到设备速率,这将不会有一个完美的持续时间。它会起作用,但是可能会有大块的边界处的点击等工件。您需要一个尚未指定或实现的功能 - 可选的AudioContext采样率 - 以解决此问题。

Brion Vibbers AudioFeeder.js很好的工作,没有任何点击,但需要原始的32位pcm数据。也要警惕upsampling artifacts

另一种选择: 您可以使用MediaSource API克服音频之间的这些毛刺。

如果您需要完整的研究,请使用:MSE for Audio