Add optional Lanczos filter to the audio mixer
Should be higher-quality than the linear-interpolator, but also much slower, so it's disabled by default.
This commit is contained in:
parent
39067057c1
commit
48386d443b
3 changed files with 47 additions and 7 deletions
|
@ -20,6 +20,7 @@ option(JAPANESE "Enable the Japanese-language build (instead of the unofficial A
|
||||||
option(FIX_BUGS "Fix various bugs in the game" OFF)
|
option(FIX_BUGS "Fix various bugs in the game" OFF)
|
||||||
option(DEBUG_SAVE "Re-enable the ability to drag-and-drop save files onto the window" OFF)
|
option(DEBUG_SAVE "Re-enable the ability to drag-and-drop save files onto the window" OFF)
|
||||||
option(DOCONFIG "Compile a DoConfig clone tool - not useful for console ports" ON)
|
option(DOCONFIG "Compile a DoConfig clone tool - not useful for console ports" ON)
|
||||||
|
option(LANCZOS_RESAMPLER "Use Lanczos filtering for audio resampling instead of linear-interpolation (Lanczos is more performance-intensive, but higher quality)" OFF)
|
||||||
|
|
||||||
set(BACKEND_RENDERER "SDLTexture" CACHE STRING "Which renderer the game should use: 'OpenGL3' for an OpenGL 3.2 renderer, 'OpenGLES2' for an OpenGL ES 2.0 renderer, 'SDLTexture' for SDL2's hardware-accelerated Texture API, 'SDLSurface' for SDL2's software-rendered Surface API, 'Wii U' for the Wii U's hardware-accelerated GX2 API, or 'Software' for a handwritten software renderer")
|
set(BACKEND_RENDERER "SDLTexture" CACHE STRING "Which renderer the game should use: 'OpenGL3' for an OpenGL 3.2 renderer, 'OpenGLES2' for an OpenGL ES 2.0 renderer, 'SDLTexture' for SDL2's hardware-accelerated Texture API, 'SDLSurface' for SDL2's software-rendered Surface API, 'Wii U' for the Wii U's hardware-accelerated GX2 API, or 'Software' for a handwritten software renderer")
|
||||||
set(BACKEND_AUDIO "SDL2" CACHE STRING "Which audio backend the game should use: 'SDL2', 'miniaudio', 'WiiU-Hardware', 'WiiU-Software', or 'Null'")
|
set(BACKEND_AUDIO "SDL2" CACHE STRING "Which audio backend the game should use: 'SDL2', 'miniaudio', 'WiiU-Hardware', 'WiiU-Software', or 'Null'")
|
||||||
|
@ -268,6 +269,10 @@ if(DEBUG_SAVE)
|
||||||
target_compile_definitions(CSE2 PRIVATE DEBUG_SAVE)
|
target_compile_definitions(CSE2 PRIVATE DEBUG_SAVE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(LANCZOS_RESAMPLER)
|
||||||
|
target_compile_definitions(CSE2 PRIVATE LANCZOS_RESAMPLER)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(PKG_CONFIG_STATIC_LIBS)
|
if(PKG_CONFIG_STATIC_LIBS)
|
||||||
target_link_options(CSE2 PRIVATE "-static")
|
target_link_options(CSE2 PRIVATE "-static")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -95,6 +95,7 @@ Name | Function
|
||||||
`-DDEBUG_SAVE=ON` | Re-enable the ability to drag-and-drop save files onto the window
|
`-DDEBUG_SAVE=ON` | Re-enable the ability to drag-and-drop save files onto the window
|
||||||
`-DDOCONFIG=OFF` | Disable compiling the DoConfig tool (it is not useful for console ports)
|
`-DDOCONFIG=OFF` | Disable compiling the DoConfig tool (it is not useful for console ports)
|
||||||
`-DDOCONFIG_LEGACY_OPENGL=ON` | Make DoConfig use OpenGL 2.1 instead of OpenGL 3.2 (useful for older/limited platforms)
|
`-DDOCONFIG_LEGACY_OPENGL=ON` | Make DoConfig use OpenGL 2.1 instead of OpenGL 3.2 (useful for older/limited platforms)
|
||||||
|
`-DLANCZOS_RESAMPLER=ON` | Use Lanczos filtering for audio resampling instead of linear-interpolation (Lanczos is more performance-intensive, but higher quality)
|
||||||
`-DBACKEND_RENDERER=OpenGL3` | Render with OpenGL 3.2 (hardware-accelerated)
|
`-DBACKEND_RENDERER=OpenGL3` | Render with OpenGL 3.2 (hardware-accelerated)
|
||||||
`-DBACKEND_RENDERER=OpenGLES2` | Render with OpenGL ES 2.0 (hardware-accelerated)
|
`-DBACKEND_RENDERER=OpenGLES2` | Render with OpenGL ES 2.0 (hardware-accelerated)
|
||||||
`-DBACKEND_RENDERER=SDLTexture` | (Default) Render with SDL2's Texture API (hardware-accelerated) (note: requires `-DBACKEND_PLATFORM=SDL2`)
|
`-DBACKEND_RENDERER=SDLTexture` | (Default) Render with SDL2's Texture API (hardware-accelerated) (note: requires `-DBACKEND_PLATFORM=SDL2`)
|
||||||
|
|
|
@ -51,7 +51,11 @@ Mixer_Sound* Mixer_CreateSound(unsigned int frequency, const unsigned char *samp
|
||||||
if (sound == NULL)
|
if (sound == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sound->samples = (signed char*)malloc(length + 1);
|
#ifdef LANCZOS_RESAMPLER
|
||||||
|
sound->samples = (signed char*)malloc(length);
|
||||||
|
#else
|
||||||
|
sound->samples = (signed char*)malloc(length + 1); // +1 for the linear-interpolator
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sound->samples == NULL)
|
if (sound->samples == NULL)
|
||||||
{
|
{
|
||||||
|
@ -96,7 +100,9 @@ void Mixer_PlaySound(Mixer_Sound *sound, bool looping)
|
||||||
sound->playing = true;
|
sound->playing = true;
|
||||||
sound->looping = looping;
|
sound->looping = looping;
|
||||||
|
|
||||||
|
#ifndef LANCZOS_RESAMPLER
|
||||||
sound->samples[sound->frames] = looping ? sound->samples[0] : 0; // For the linear interpolator
|
sound->samples[sound->frames] = looping ? sound->samples[0] : 0; // For the linear interpolator
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mixer_StopSound(Mixer_Sound *sound)
|
void Mixer_StopSound(Mixer_Sound *sound)
|
||||||
|
@ -143,15 +149,43 @@ ATTRIBUTE_HOT void Mixer_MixSounds(long *stream, size_t frames_total)
|
||||||
|
|
||||||
for (size_t frames_done = 0; frames_done < frames_total; ++frames_done)
|
for (size_t frames_done = 0; frames_done < frames_total; ++frames_done)
|
||||||
{
|
{
|
||||||
// Perform linear interpolation
|
#ifdef LANCZOS_RESAMPLER
|
||||||
const unsigned char subsample = sound->position_subsample >> 8;
|
// Perform Lanczos resampling
|
||||||
|
const int kernel_radius = 2;
|
||||||
|
|
||||||
const short interpolated_sample = sound->samples[sound->position] * (0x100 - subsample)
|
double accumulator = 0;
|
||||||
+ sound->samples[sound->position + 1] * subsample;
|
|
||||||
|
for (int i = -MIN(kernel_radius - 1, sound->position); i <= kernel_radius; ++i)
|
||||||
|
{
|
||||||
|
const signed char input_sample = sound->samples[(sound->position + i) % sound->frames];
|
||||||
|
|
||||||
|
const double kernel_input = ((double)sound->position_subsample / 0x10000) - i;
|
||||||
|
|
||||||
|
if (kernel_input == 0.0)
|
||||||
|
{
|
||||||
|
accumulator += input_sample;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const double nx = 3.14159265358979323846 * kernel_input;
|
||||||
|
const double nxa = nx / kernel_radius;
|
||||||
|
|
||||||
|
accumulator += input_sample * (sin(nx) / nx) * (sin(nxa) / nxa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const short output_sample = (short)(accumulator * 0x100);
|
||||||
|
#else
|
||||||
|
// Perform linear interpolation
|
||||||
|
const unsigned char interpolation_scale = sound->position_subsample >> 8;
|
||||||
|
|
||||||
|
const short output_sample = sound->samples[sound->position] * (0x100 - interpolation_scale)
|
||||||
|
+ sound->samples[sound->position + 1] * interpolation_scale;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Mix, and apply volume
|
// Mix, and apply volume
|
||||||
*stream_pointer++ += (interpolated_sample * sound->volume_l) >> 8;
|
*stream_pointer++ += (output_sample * sound->volume_l) >> 8;
|
||||||
*stream_pointer++ += (interpolated_sample * sound->volume_r) >> 8;
|
*stream_pointer++ += (output_sample * sound->volume_r) >> 8;
|
||||||
|
|
||||||
// Increment sample
|
// Increment sample
|
||||||
const unsigned long next_position_subsample = sound->position_subsample + sound->advance_delta;
|
const unsigned long next_position_subsample = sound->position_subsample + sound->advance_delta;
|
||||||
|
|
Loading…
Add table
Reference in a new issue