From 961c1344ebfa4a68dc5a604e6d929c5f3981eaa4 Mon Sep 17 00:00:00 2001 From: Luke Hubmayer-Werner Date: Tue, 16 Jul 2024 21:59:51 +0930 Subject: [PATCH] [BGM] Try cubic instead of sinc interpolation Ported the godot implementation --- shaders/audio_renderer.gdshader | 49 +++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/shaders/audio_renderer.gdshader b/shaders/audio_renderer.gdshader index ea5602a..70821e4 100644 --- a/shaders/audio_renderer.gdshader +++ b/shaders/audio_renderer.gdshader @@ -103,7 +103,7 @@ highp vec2 pack_float_to_int16(highp float value) { const highp float HEADER_LENGTH_TEXELS = 5.0; const highp int INSTRUMENT_SAMPLES_WIDTH = 2048; highp float sinc(highp float x) { - x = abs(x) + 0.00000000000001; // Avoid division by zero + x = abs(x * 3.14159265359) + 0.00000000001; // Avoid division by zero return min(sin(x)/x, 1.0); } @@ -133,21 +133,40 @@ highp float get_instrument_sample(highp float instrument_index, highp float note // If we're past the end of the sample, we need to wrap it back to within the loop range highp float overshoot = max(smp_t - smp_loop_begin, 0.0); smp_t -= floor(overshoot/smp_loop_length) * smp_loop_length; - // if (smp_t > smp_loop_begin) { - // // return 0.0; - // smp_t = mod(smp_t - smp_loop_begin, smp_loop_length) + smp_loop_begin; - // } - highp int smp_window_start = smp_start + int(smp_t) - 6; - highp float smp_rel_filter_target = fract(smp_t) + 6.0; - highp float output = 0.0; - for (int i = 0; i < 12; i++) { - highp int smp_filter = smp_window_start + i; - highp float s = get_inst_texel_int16(smp_filter); - // TODO: determine proper value for this. Might be based on instrument base mixrate. - output += s * sinc((smp_rel_filter_target - float(i)) * 3.1); - } - return rescale_int16(output); + // // Linear interpolation + // highp int smp_window_start = smp_start + int(smp_t); + // highp float x0 = get_inst_texel_int16(smp_window_start); + // highp float x1 = get_inst_texel_int16(smp_window_start+1); + // return rescale_int16(mix(x0, x1, fract(smp_t))); + + // Cubic interpolation + highp int smp_window_start = smp_start + int(smp_t); + highp float x0 = get_inst_texel_int16(smp_window_start-1); + highp float x1 = get_inst_texel_int16(smp_window_start); + highp float x2 = get_inst_texel_int16(smp_window_start+1); + highp float x3 = get_inst_texel_int16(smp_window_start+2); + highp float a0 = 3.0*x1 - 3.0*x2 + x3 - x0; + highp float a1 = 2.0*x0 - 5.0*x1 + 4.0*x2 - x3; + highp float a2 = x2 - x0; + highp float a3 = 2.0*x1; + highp float T = fract(smp_t); + highp float T2 = T*T; + return rescale_int16((a0*T2*T + a1*T2 + a2*T + a3) / 2.0); + + // // Windowed Sinc interpolation + // highp int smp_window_start = smp_start + int(smp_t) - 6; + // highp float smp_rel_filter_target = fract(smp_t) + 6.0; + // highp float output = 0.0; + // for (int i = 0; i < 12; i++) { + // highp int smp_filter = smp_window_start + i; + // highp float s = get_inst_texel_int16(smp_filter); + // // TODO: determine proper value for this. Might be based on instrument base mixrate. + // output += s * sinc(smp_rel_filter_target - float(i)); + // } + // return rescale_int16(output); + + // // Nearest sample // int target_texel = int(smp_t) + smp_start; // return rescale_int16(get_inst_texel_int16(target_texel)); }