[BGM] Try cubic instead of sinc interpolation

Ported the godot implementation
This commit is contained in:
Luke Hubmayer-Werner 2024-07-16 21:59:51 +09:30
parent 72dcc11945
commit 961c1344eb
1 changed files with 34 additions and 15 deletions

View File

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