diff --git a/libgambatte/Makefile.libretro b/libgambatte/Makefile.libretro index 2d0f5b3..7d57c2c 100644 --- a/libgambatte/Makefile.libretro +++ b/libgambatte/Makefile.libretro @@ -81,9 +81,10 @@ else ifeq ($(platform), psp1) CC = psp-gcc$(EXE_EXT) CXX = psp-g++$(EXE_EXT) AR = psp-ar$(EXE_EXT) - PLATFORM_DEFINES := -DPSP - CFLAGS += -G0 - STATIC_LINKING = 1 + PLATFORM_DEFINES := -DPSP -DALTERNATIVE_RESAMPLER + CFLAGS += -G0 + CXXFLAGS += -G0 + STATIC_LINKING = 1 else ifeq ($(platform), xenon) TARGET := $(TARGET_NAME)_libretro_xenon360.a CC = xenon-gcc$(EXE_EXT) diff --git a/libgambatte/libretro/libretro.cpp b/libgambatte/libretro/libretro.cpp index 5e7dfcc..10c7ea5 100644 --- a/libgambatte/libretro/libretro.cpp +++ b/libgambatte/libretro/libretro.cpp @@ -44,8 +44,10 @@ class SNESInput : public gambatte::InputGetter } } static gb_input; +#ifndef ALTERNATIVE_RESAMPLER static blipper_t *resampler_l; static blipper_t *resampler_r; +#endif void retro_get_system_info(struct retro_system_info *info) { @@ -80,7 +82,7 @@ void retro_init() double fps = 4194304.0 / 70224.0; double sample_rate = fps * 35112; - +#ifndef ALTERNATIVE_RESAMPLER resampler_l = blipper_new(32, 0.85, 6.5, 64, 1024, NULL); resampler_r = blipper_new(32, 0.85, 6.5, 64, 1024, NULL); @@ -89,12 +91,21 @@ void retro_init() g_timing.fps = fps; g_timing.sample_rate = sample_rate / 64; // ~32k } +#else + if (environ_cb) + { + g_timing.fps = fps; + g_timing.sample_rate = sample_rate / 32; // ~64k + } +#endif } void retro_deinit() { +#ifndef ALTERNATIVE_RESAMPLER blipper_free(resampler_l);; blipper_free(resampler_r);; +#endif } void retro_set_environment(retro_environment_t cb) @@ -424,6 +435,7 @@ size_t retro_get_memory_size(unsigned id) return 0; } +#ifndef ALTERNATIVE_RESAMPLER static void render_audio(const int16_t *samples, unsigned frames) { if (!frames) @@ -432,12 +444,35 @@ static void render_audio(const int16_t *samples, unsigned frames) blipper_push_samples(resampler_l, samples + 0, frames, 2); blipper_push_samples(resampler_r, samples + 1, frames, 2); } +#endif void retro_run() { static uint64_t samples_count = 0; static uint64_t frames_count = 0; +#ifdef ALTERNATIVE_RESAMPLER + static const int16_t CS_kernel[32]= + { + 0x01FF, 0x01FE, 0x01FA, 0x01F4, 0x01EC, 0x01E1, 0x01D4, 0x01C5, + 0x01B4, 0x01A2, 0x018E, 0x0178, 0x0161, 0x014A, 0x0131, 0x0119, + 0x0100, 0x00E6, 0x00CE, 0x00B5, 0x009E, 0x0087, 0x0071, 0x005D, + 0x004B, 0x003A, 0x002B, 0x001E, 0x0013, 0x000B, 0x0005, 0x0001 + }; + static int32_t l_sample_current = 0; + static int32_t r_sample_current = 0; + static int32_t l_sample_next = 0; + static int32_t r_sample_next = 0; + static int32_t capacitor = 0; + static unsigned int accumulated_samples = 0; + static unsigned int write_pos = 0; + union + { + gambatte::uint_least32_t u32[512]; + int16_t i16[2 * 512]; + } static out_buf; +#endif + input_poll_cb(); uint64_t expected_frames = samples_count / 35112; @@ -463,6 +498,8 @@ void retro_run() gambatte::uint_least32_t video_pitch = 256; while (gb.runFor(video_buf, video_pitch, sound_buf.u32, samples) == -1) { + +#ifndef ALTERNATIVE_RESAMPLER render_audio(sound_buf.i16, samples); unsigned read_avail = blipper_read_avail(resampler_l); @@ -472,13 +509,42 @@ void retro_run() blipper_read(resampler_r, sound_buf.i16 + 1, read_avail, 2); audio_batch_cb(sound_buf.i16, read_avail); } +#else + for (int i=0; i < (samples << 1); i+=2) + { + l_sample_current += sound_buf.i16[i] * CS_kernel[accumulated_samples]; + l_sample_next += sound_buf.i16[i] * CS_kernel[31 - accumulated_samples]; + r_sample_current += sound_buf.i16[i + 1] * CS_kernel[accumulated_samples]; + r_sample_next += sound_buf.i16[i + 1] * CS_kernel[31 - accumulated_samples]; + accumulated_samples++; + if (accumulated_samples == 32) + { + capacitor += ((l_sample_current ) - capacitor) >> 14; + out_buf.i16[write_pos++] = (l_sample_current>>14) - (capacitor >> 14); + out_buf.i16[write_pos++] = (r_sample_current>>14) - (capacitor >> 14); + accumulated_samples = 0; + l_sample_current = l_sample_next; + r_sample_current = r_sample_next; + l_sample_next = 0; + r_sample_next = 0; + + if (write_pos == 1024){ + audio_batch_cb(out_buf.i16, 512); + write_pos = 0; + } + } + } +#endif samples_count += samples; samples = 2064; } samples_count += samples; + +#ifndef ALTERNATIVE_RESAMPLER render_audio(sound_buf.i16, samples); +#endif #ifdef VIDEO_RGB565 video_cb(video_buf, 160, 144, 512); @@ -486,10 +552,38 @@ void retro_run() video_cb(video_buf, 160, 144, 1024); #endif +#ifndef ALTERNATIVE_RESAMPLER unsigned read_avail = blipper_read_avail(resampler_l); blipper_read(resampler_l, sound_buf.i16 + 0, read_avail, 2); blipper_read(resampler_r, sound_buf.i16 + 1, read_avail, 2); audio_batch_cb(sound_buf.i16, read_avail); +#else + for (int i=0; i < (samples << 1); i+=2) + { + l_sample_current += sound_buf.i16[i] * CS_kernel[accumulated_samples]; + l_sample_next += sound_buf.i16[i] * CS_kernel[31 - accumulated_samples]; + r_sample_current += sound_buf.i16[i + 1] * CS_kernel[accumulated_samples]; + r_sample_next += sound_buf.i16[i + 1] * CS_kernel[31 - accumulated_samples]; + accumulated_samples++; + if (accumulated_samples == 32) + { + capacitor += ((l_sample_current ) - capacitor) >> 14; + out_buf.i16[write_pos++] = (l_sample_current>>14) - (capacitor >> 14); + out_buf.i16[write_pos++] = (r_sample_current>>14) - (capacitor >> 14); + + accumulated_samples = 0; + l_sample_current = l_sample_next; + r_sample_current = r_sample_next; + l_sample_next = 0; + r_sample_next = 0; + + if (write_pos == 1024){ + audio_batch_cb(out_buf.i16, 512); + write_pos = 0; + } + } + } +#endif frames_count++;