From cc79342c5bbd26bf296a46b9c73d92c85c6eaa05 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 3 Jan 2025 02:18:35 -0800 Subject: [PATCH] Audio/extrapolator: Fix short prime length When the input buffer has less samples in it than the LPC order, it would crash reaching past the ends of the buffer. Now, it will pad past the correct end of the audio with silence, while still extrapolating a prime input minimum of the LPC order. Should fix the last of the outstanding crashes. Signed-off-by: Christopher Snowhill --- Audio/ThirdParty/lvqcl/lpc.c | 49 +++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/Audio/ThirdParty/lvqcl/lpc.c b/Audio/ThirdParty/lvqcl/lpc.c index 29f634578..201baf94a 100644 --- a/Audio/ThirdParty/lvqcl/lpc.c +++ b/Audio/ThirdParty/lvqcl/lpc.c @@ -139,7 +139,10 @@ static void vorbis_lpc_predict(float *coeff, float *prime, int m, float *data, l } void lpc_extrapolate2(float *const data, const size_t data_len, const int nch, const int lpc_order, const size_t extra_bkwd, const size_t extra_fwd, void **extrapolate_buffer, size_t *extrapolate_buffer_size) { - const size_t tdata_size = sizeof(float) * (extra_bkwd + data_len + extra_fwd); + const size_t max_to_prime = (data_len < lpc_order) ? data_len : lpc_order; + const size_t min_data_len = (data_len < lpc_order) ? lpc_order : data_len; + + const size_t tdata_size = sizeof(float) * (extra_bkwd + min_data_len + extra_fwd); const size_t aut_size = sizeof(double) * (lpc_order + 1); const size_t lpc_size = sizeof(double) * lpc_order; const size_t lpci_size = sizeof(float) * lpc_order; @@ -162,32 +165,54 @@ void lpc_extrapolate2(float *const data, const size_t data_len, const int nch, c for(int c = 0; c < nch; c++) { if(extra_bkwd) { for(int i = 0; i < (int)data_len; i++) - tdata[data_len - 1 - i] = data[i * nch + c]; + tdata[min_data_len - 1 - i] = data[i * nch + c]; + if(data_len < min_data_len) + for(int i = (int)data_len; i < (int)min_data_len; i++) + tdata[min_data_len - 1 - i] = 0.0f; } else { - for(int i = 0; i < (int)data_len; i++) - tdata[i] = data[i * nch + c]; + const ssize_t len_diff = min_data_len - data_len; + if(len_diff <= 0) { + for(int i = 0; i < (int)data_len; i++) + tdata[i] = data[i * nch + c]; + } else { + for(int i = 0; i < (int)len_diff; i++) + tdata[i] = 0.0f; + for(int i = 0; i < (int)data_len; i++) + tdata[len_diff + i] = data[i * nch + c]; + } } - apply_window(tdata, data_len); - vorbis_lpc_from_data(tdata, lpci, (int)data_len, lpc_order, aut, lpc); + apply_window(tdata, min_data_len); + vorbis_lpc_from_data(tdata, lpci, (int)min_data_len, lpc_order, aut, lpc); // restore after apply_window if(extra_bkwd) { for(int i = 0; i < (int)data_len; i++) - tdata[data_len - 1 - i] = data[i * nch + c]; + tdata[min_data_len - 1 - i] = data[i * nch + c]; + if(data_len < min_data_len) + for(int i = (int)data_len; i < (int)min_data_len; i++) + tdata[min_data_len - 1 - i] = 0.0f; } else { - for(int i = 0; i < (int)data_len; i++) - tdata[i] = data[i * nch + c]; + const ssize_t len_diff = min_data_len - data_len; + if(len_diff <= 0) { + for(int i = 0; i < (int)data_len; i++) + tdata[i] = data[i * nch + c]; + } else { + for(int i = 0; i < (int)len_diff; i++) + tdata[i] = 0.0f; + for(int i = 0; i < (int)data_len; i++) + tdata[len_diff + i] = data[i * nch + c]; + } } - vorbis_lpc_predict(lpci, tdata + data_len - lpc_order, lpc_order, tdata + data_len, extra_fwd + extra_bkwd, work); + vorbis_lpc_predict(lpci, tdata + min_data_len - lpc_order, lpc_order, tdata + min_data_len, extra_fwd + extra_bkwd, work); if(extra_bkwd) { for(int i = 0; i < extra_bkwd; i++) - data[(-i - 1) * nch + c] = tdata[data_len + i]; + data[(-i - 1) * nch + c] = tdata[min_data_len + i]; } else { for(int i = 0; i < extra_fwd; i++) - data[(i + data_len) * nch + c] = tdata[data_len + i]; + data[(i + data_len) * nch + c] = tdata[min_data_len + i]; } } }