Add hermite resampler core :) SRC is disabled by default.

This commit is contained in:
Themaister 2011-02-06 13:29:48 +01:00
parent caf3eb7b05
commit 820b124165
9 changed files with 75 additions and 20 deletions

View File

@ -19,6 +19,8 @@ endif
ifeq ($(HAVE_SRC), 1)
LIBS += $(SRC_LIBS)
DEFINES += $(SRC_CFLAGS)
else
OBJ += audio/hermite.o
endif
ifeq ($(HAVE_CONFIGFILE), 1)

View File

@ -18,13 +18,13 @@ SSNES requires these libraries to build:
- [libsnes](http://byuu.org/bsnes/)
- SDL
- libsamplerate
SSNES can utilize these libraries if enabled:
- nvidia-cg-toolkit
- libxml2 (bSNES XML shaders)
- libfreetype2 (TTF font rendering on screen)
- libsamplerate
SSNES needs at least one of these audio driver libraries:

View File

@ -38,8 +38,6 @@
#ifdef HAVE_SRC
#include <samplerate.h>
#else
#error HAVE_SRC is not defined!
#endif
@ -144,7 +142,9 @@ static const int out_latency = 64;
static const bool audio_sync = true;
// Defines the quality (and cpu reqirements) of samplerate conversion.
#ifdef HAVE_SRC
#define SAMPLERATE_QUALITY SRC_LINEAR
#endif
// Enables use of rewind. This will incur some memory footprint depending on the save state buffer.
// This rewind only works when using bSNES core atm.

View File

@ -166,10 +166,16 @@ void init_audio(void)
else
g_extern.audio_data.chunk_size = g_extern.audio_data.block_chunk_size;
#ifdef HAVE_SRC
int err;
g_extern.source = src_new(g_settings.audio.src_quality, 2, &err);
if (!g_extern.source)
g_extern.audio_data.source = src_new(g_settings.audio.src_quality, 2, &err);
if (!g_extern.audio_data.source)
g_extern.audio_active = false;
#else
g_extern.audio_data.source = hermite_new();
if (!g_extern.audio_data.source)
g_extern.audio_active = false;
#endif
size_t max_bufsamples = g_extern.audio_data.block_chunk_size > g_extern.audio_data.nonblock_chunk_size ?
g_extern.audio_data.block_chunk_size : g_extern.audio_data.nonblock_chunk_size;
@ -192,8 +198,14 @@ void uninit_audio(void)
if ( driver.audio_data && driver.audio )
driver.audio->free(driver.audio_data);
if ( g_extern.source )
src_delete(g_extern.source);
if ( g_extern.audio_data.source )
{
#ifdef HAVE_SRC
src_delete(g_extern.audio_data.source);
#else
hermite_free(g_extern.audio_data.source);
#endif
}
free(g_extern.audio_data.data); g_extern.audio_data.data = NULL;
free(g_extern.audio_data.outsamples); g_extern.audio_data.outsamples = NULL;

View File

@ -33,6 +33,8 @@
#ifdef HAVE_SRC
#include <samplerate.h>
#else
#include "audio/hermite.h"
#endif
@ -106,7 +108,6 @@ enum ssnes_game_type
struct global
{
bool verbose;
SRC_STATE *source;
bool audio_active;
bool video_active;
@ -140,6 +141,12 @@ struct global
struct
{
#ifdef HAVE_SRC
SRC_STATE *source;
#else
hermite_resampler_t *source;
#endif
float *data;
size_t data_ptr;
size_t chunk_size;

View File

@ -46,7 +46,6 @@ if [ $HAVE_FFMPEG != no ]; then
fi
check_pkgconf SRC samplerate
check_critical SRC "Cannot find libsamplerate."
check_lib DYNAMIC -ldl dlopen

View File

@ -11,6 +11,7 @@ add_command_line_enable DYNAMIC "Enable dynamic loading of libsnes library." no
add_command_line_string LIBSNES "libsnes library used" "-lsnes"
add_command_line_enable FFMPEG "Enable FFmpeg recording support" no
add_command_line_enable FILTER "Enable CPU filter support" no
add_command_line_enable SRC "Enable libsamplerate support" no
add_command_line_enable CONFIGFILE "Disable support for config file" yes
add_command_line_enable CG "Enable Cg shader support" auto
add_command_line_enable XML "Enable bSNES-style XML shader support" auto

View File

@ -122,7 +122,10 @@ static void set_defaults(void)
strncpy(g_settings.audio.device, audio_device, sizeof(g_settings.audio.device));
g_settings.audio.latency = out_latency;
g_settings.audio.sync = audio_sync;
#ifdef HAVE_SRC
g_settings.audio.src_quality = SAMPLERATE_QUALITY;
#endif
g_settings.rewind_enable = rewind_enable;
g_settings.rewind_buffer_size = rewind_buffer_size;
@ -300,6 +303,7 @@ static void parse_config_file(void)
CONFIG_GET_INT(audio.latency, "audio_latency");
CONFIG_GET_BOOL(audio.sync, "audio_sync");
#ifdef HAVE_SRC
if (config_get_int(conf, "audio_src_quality", &tmp_int))
{
int quals[] = { SRC_ZERO_ORDER_HOLD, SRC_LINEAR, SRC_SINC_FASTEST,
@ -308,6 +312,7 @@ static void parse_config_file(void)
if (tmp_int > 0 && tmp_int < 6)
g_settings.audio.src_quality = quals[tmp_int];
}
#endif
CONFIG_GET_STRING(video.driver, "video_driver");
CONFIG_GET_STRING(audio.driver, "audio_driver");

51
ssnes.c
View File

@ -179,8 +179,8 @@ static void audio_sample(uint16_t left, uint16_t right)
}
#endif
g_extern.audio_data.data[g_extern.audio_data.data_ptr++] = (float)(*(int16_t*)&left)/0x8000;
g_extern.audio_data.data[g_extern.audio_data.data_ptr++] = (float)(*(int16_t*)&right)/0x8000;
g_extern.audio_data.data[g_extern.audio_data.data_ptr++] = (float)(int16_t)left/0x8000;
g_extern.audio_data.data[g_extern.audio_data.data_ptr++] = (float)(int16_t)right/0x8000;
if (g_extern.audio_data.data_ptr >= g_extern.audio_data.chunk_size)
{
@ -188,20 +188,37 @@ static void audio_sample(uint16_t left, uint16_t right)
if (g_extern.frame_is_reverse) // Disable fucked up audio when rewinding...
memset(g_extern.audio_data.data, 0, g_extern.audio_data.chunk_size * sizeof(float));
SRC_DATA src_data;
#ifdef HAVE_SRC
SRC_DATA src_data = {
.data_in = g_extern.audio_data.data,
.data_out = g_extern.audio_data.outsamples,
.input_frames = g_extern.audio_data.chunk_size / 2,
.output_frames = g_extern.audio_data.chunk_size * 8,
.end_of_input = 0,
.src_ratio = (double)g_settings.audio.out_rate / (double)g_settings.audio.in_rate,
};
#else
struct hermite_data re_data = {
.in_data = g_extern.audio_data.data,
.out_data = g_extern.audio_data.outsamples,
.in_frames = g_extern.audio_data.chunk_size / 2,
.ratio = (double)g_settings.audio.out_rate / (double)g_settings.audio.in_rate,
};
#endif
src_data.data_in = g_extern.audio_data.data;
src_data.data_out = g_extern.audio_data.outsamples;
src_data.input_frames = g_extern.audio_data.chunk_size / 2;
src_data.output_frames = g_extern.audio_data.chunk_size * 8;
src_data.end_of_input = 0;
src_data.src_ratio = (double)g_settings.audio.out_rate / (double)g_settings.audio.in_rate;
src_process(g_extern.source, &src_data);
#ifdef HAVE_SRC
src_process(g_extern.audio_data.source, &src_data);
#else
size_t output_frames_gen = hermite_process(g_extern.audio_data.source, &re_data);
#endif
if (g_extern.audio_data.use_float)
{
#ifdef HAVE_SRC
if (driver.audio->write(driver.audio_data, g_extern.audio_data.outsamples, src_data.output_frames_gen * sizeof(float) * 2) < 0)
#else
if (driver.audio->write(driver.audio_data, g_extern.audio_data.outsamples, output_frames_gen * sizeof(float) * 2) < 0)
#endif
{
fprintf(stderr, "SSNES [ERROR]: Audio backend failed to write. Will continue without sound.\n");
g_extern.audio_active = false;
@ -209,9 +226,21 @@ static void audio_sample(uint16_t left, uint16_t right)
}
else
{
#ifdef HAVE_SRC
src_float_to_short_array(g_extern.audio_data.outsamples, g_extern.audio_data.conv_outsamples, src_data.output_frames_gen * 2);
#else
for (unsigned i = 0; i < output_frames_gen * 2; i++)
{
int32_t val = g_extern.audio_data.outsamples[i] * 0x8000;
g_extern.audio_data.conv_outsamples[i] = (val > 0x7FFF) ? 0x7FFF : (val < -0x8000 ? -0x8000 : (int16_t)val);
}
#endif
#ifdef HAVE_SRC
if (driver.audio->write(driver.audio_data, g_extern.audio_data.conv_outsamples, src_data.output_frames_gen * sizeof(int16_t) * 2) < 0)
#else
if (driver.audio->write(driver.audio_data, g_extern.audio_data.conv_outsamples, output_frames_gen * sizeof(int16_t) * 2) < 0)
#endif
{
fprintf(stderr, "SSNES [ERROR]: Audio backend failed to write. Will continue without sound.\n");
g_extern.audio_active = false;