kill client-side early rebuffering, improving the latency
This commit is contained in:
parent
93d4e629d1
commit
0b2c457030
@ -181,11 +181,6 @@ sdrs = {
|
||||
|
||||
# ==== Misc settings ====
|
||||
|
||||
client_audio_buffer_size = 5
|
||||
# increasing client_audio_buffer_size will:
|
||||
# - also increase the latency
|
||||
# - decrease the chance of audio underruns
|
||||
|
||||
iq_port_range = [
|
||||
4950,
|
||||
4960,
|
||||
|
@ -1115,7 +1115,6 @@ function on_ws_recv(evt) {
|
||||
|
||||
window.starting_mod = config['start_mod'];
|
||||
window.starting_offset_frequency = config['start_offset_freq'];
|
||||
window.audio_buffering_fill_to = config['client_audio_buffer_size'];
|
||||
bandwidth = config['samp_rate'];
|
||||
center_freq = config['center_freq'] + config['lfo_offset'];
|
||||
fft_size = config['fft_size'];
|
||||
@ -1258,7 +1257,7 @@ function on_ws_recv(evt) {
|
||||
audio_prepare(audio_data);
|
||||
audio_buffer_current_size_debug += audio_data.length;
|
||||
audio_buffer_all_size_debug += audio_data.length;
|
||||
if (!(ios || is_chrome) && (audio_initialized === 0 && audio_prepared_buffers.length > audio_buffering_fill_to)) audio_init();
|
||||
if (!(ios || is_chrome) && (audio_initialized === 0)) audio_init();
|
||||
break;
|
||||
case 3:
|
||||
// secondary FFT
|
||||
@ -1536,12 +1535,8 @@ var audio_buffer_maximal_length_sec = 3; //actual number of samples are calculat
|
||||
var audio_buffer_decrease_to_on_overrun_sec = 2.2;
|
||||
var audio_flush_interval_ms = 500; //the interval in which audio_flush() is called
|
||||
|
||||
var audio_prepared_buffers = Array();
|
||||
var audio_rebuffer;
|
||||
var audio_buffers = [];
|
||||
var audio_last_output_buffer;
|
||||
var audio_buffering = false;
|
||||
//var audio_buffering_fill_to=4; //on audio underrun we wait until this n*audio_buffer_size samples are present
|
||||
//tnx to the hint from HA3FLT, now we have about half the response time! (original value: 10)
|
||||
|
||||
function gain_ff(gain_value, data) //great! solved clicking! will have to move to sdr.js
|
||||
{
|
||||
@ -1551,24 +1546,12 @@ function gain_ff(gain_value, data) //great! solved clicking! will have to move t
|
||||
}
|
||||
|
||||
function audio_prepare(data) {
|
||||
|
||||
//audio_rebuffer.push(sdrjs.ConvertI16_F(data));//no resampling
|
||||
//audio_rebuffer.push(audio_resampler.process(sdrjs.ConvertI16_F(data)));//resampling without ADPCM
|
||||
if (audio_compression === "none")
|
||||
audio_rebuffer.push(audio_resampler.process(gain_ff(volume, sdrjs.ConvertI16_F(data))));//resampling without ADPCM
|
||||
else if (audio_compression === "adpcm")
|
||||
audio_rebuffer.push(audio_resampler.process(gain_ff(volume, sdrjs.ConvertI16_F(audio_codec.decode(data))))); //resampling & ADPCM
|
||||
else return;
|
||||
|
||||
//console.log("prepare",data.length,audio_rebuffer.remaining());
|
||||
while (audio_rebuffer.remaining()) {
|
||||
audio_prepared_buffers.push(audio_rebuffer.take());
|
||||
audio_buffer_current_count_debug++;
|
||||
}
|
||||
if (audio_buffering && audio_prepared_buffers.length > audio_buffering_fill_to) {
|
||||
console.log("buffers now: " + audio_prepared_buffers.length.toString());
|
||||
audio_buffering = false;
|
||||
var buffer = data;
|
||||
if (audio_compression === "adpcm") {
|
||||
//resampling & ADPCM
|
||||
buffer = audio_codec.decode(buffer);
|
||||
}
|
||||
audio_buffers.push(audio_resampler.process(gain_ff(volume, sdrjs.ConvertI16_F(buffer))));
|
||||
}
|
||||
|
||||
if (!AudioBuffer.prototype.copyToChannel) { //Chrome 36 does not have it, Firefox does
|
||||
@ -1579,45 +1562,50 @@ if (!AudioBuffer.prototype.copyToChannel) { //Chrome 36 does not have it, Firefo
|
||||
}
|
||||
}
|
||||
|
||||
var silence = new Float32Array(4096);
|
||||
|
||||
function audio_onprocess(e) {
|
||||
if (audio_buffering) {
|
||||
e.outputBuffer.copyToChannel(silence, 0);
|
||||
return;
|
||||
}
|
||||
if (audio_prepared_buffers.length === 0) {
|
||||
audio_buffer_progressbar_update();
|
||||
audio_buffering = true;
|
||||
e.outputBuffer.copyToChannel(silence, 0);
|
||||
var total = 0;
|
||||
var out = new Float32Array(audio_buffer_size);
|
||||
while (audio_buffers.length) {
|
||||
var b = audio_buffers.shift();
|
||||
var newLength = total + b.length;
|
||||
// not enough space to fit all data, so splice and put back in the queue
|
||||
if (newLength > audio_buffer_size) {
|
||||
var tokeep = b.slice(0, audio_buffer_size - total);
|
||||
out.set(tokeep, total);
|
||||
var tobuffer = b.slice(audio_buffer_size - total, b.length);
|
||||
audio_buffers.unshift(tobuffer);
|
||||
break;
|
||||
} else {
|
||||
var buf = audio_prepared_buffers.shift();
|
||||
e.outputBuffer.copyToChannel(buf, 0);
|
||||
out.set(b, total);
|
||||
}
|
||||
total = newLength;
|
||||
}
|
||||
|
||||
e.outputBuffer.copyToChannel(out, 0);
|
||||
}
|
||||
|
||||
var audio_buffer_progressbar_update_disabled = false;
|
||||
|
||||
var audio_buffer_total_average_level = 0;
|
||||
var audio_buffer_total_average_level_length = 0;
|
||||
var audio_overrun_cnt = 0;
|
||||
var audio_underrun_cnt = 0;
|
||||
|
||||
function audio_buffers_total_length() {
|
||||
return audio_buffers.map(function(b){ return b.length; }).reduce(function(a, b){ return a + b; }, 0);
|
||||
}
|
||||
|
||||
function audio_buffer_progressbar_update() {
|
||||
if (audio_buffer_progressbar_update_disabled) return;
|
||||
var audio_buffer_value = (audio_prepared_buffers.length * audio_buffer_size) / audio_context.sampleRate;
|
||||
var audio_buffer_value = audio_buffers_total_length() / audio_context.sampleRate;
|
||||
audio_buffer_total_average_level_length++;
|
||||
audio_buffer_total_average_level = (audio_buffer_total_average_level * ((audio_buffer_total_average_level_length - 1) / audio_buffer_total_average_level_length)) + (audio_buffer_value / audio_buffer_total_average_level_length);
|
||||
var overrun = audio_buffer_value > audio_buffer_maximal_length_sec;
|
||||
var underrun = audio_prepared_buffers.length === 0;
|
||||
var underrun = audio_buffers.length === 0;
|
||||
var text = "buffer";
|
||||
if (overrun) {
|
||||
text = "overrun";
|
||||
console.log("audio overrun, " + (++audio_overrun_cnt).toString());
|
||||
}
|
||||
if (underrun) {
|
||||
text = "underrun";
|
||||
console.log("audio underrun, " + (++audio_underrun_cnt).toString());
|
||||
}
|
||||
if (overrun || underrun) {
|
||||
audio_buffer_progressbar_update_disabled = true;
|
||||
@ -1633,12 +1621,12 @@ function audio_buffer_progressbar_update() {
|
||||
function audio_flush() {
|
||||
var flushed = false;
|
||||
var we_have_more_than = function (sec) {
|
||||
return sec * audio_context.sampleRate < audio_prepared_buffers.length * audio_buffer_size;
|
||||
return sec * audio_context.sampleRate < audio_buffers_total_length();
|
||||
};
|
||||
if (we_have_more_than(audio_buffer_maximal_length_sec)) while (we_have_more_than(audio_buffer_decrease_to_on_overrun_sec)) {
|
||||
if (!flushed) audio_buffer_progressbar_update();
|
||||
flushed = true;
|
||||
audio_prepared_buffers.shift();
|
||||
audio_buffers.shift();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1690,13 +1678,11 @@ function audio_preinit() {
|
||||
else if (audio_context.sampleRate > 44100 * 4)
|
||||
audio_buffer_size = 4096 * 4;
|
||||
|
||||
if (!audio_rebuffer) {
|
||||
audio_rebuffer = new sdrjs.Rebuffer(audio_buffer_size, sdrjs.REBUFFER_FIXED);
|
||||
audio_last_output_buffer = new Float32Array(audio_buffer_size);
|
||||
|
||||
//we send our setup packet
|
||||
// TODO this should be moved to another stage of initialization
|
||||
parsehash();
|
||||
|
||||
if (!audio_resampler) {
|
||||
audio_calculate_resampling(audio_context.sampleRate);
|
||||
audio_resampler = new sdrjs.RationalResamplerFF(audio_client_resampling_factor, 1);
|
||||
}
|
||||
|
@ -65,7 +65,6 @@ class OpenWebRxReceiverClient(Client):
|
||||
"fft_compression",
|
||||
"max_clients",
|
||||
"start_mod",
|
||||
"client_audio_buffer_size",
|
||||
"start_freq",
|
||||
"center_freq",
|
||||
"mathbox_waterfall_colors",
|
||||
|
Loading…
Reference in New Issue
Block a user