mirror of
https://github.com/libretro/RetroArch
synced 2025-03-25 16:44:01 +00:00
Samplerate stuff
This commit is contained in:
parent
7c678fc334
commit
d3cec173ac
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ CFLAGS = -O3 -march=native -Wall
|
|||||||
OBJ = ssnes.o
|
OBJ = ssnes.o
|
||||||
SOBJ = libsnes.so
|
SOBJ = libsnes.so
|
||||||
|
|
||||||
LIBS = -lrsound -lglfw
|
LIBS = -lrsound -lglfw -lsamplerate
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCE) $(SOBJ) $(LIBS)
|
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCE) $(SOBJ) $(LIBS)
|
||||||
|
7
config.h
7
config.h
@ -36,6 +36,13 @@ static const unsigned fullscreen_y = 1200;
|
|||||||
// Video VSYNC (recommended)
|
// Video VSYNC (recommended)
|
||||||
static const bool vsync = true;
|
static const bool vsync = true;
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
static const unsigned out_rate = 48000;
|
||||||
|
|
||||||
|
static const unsigned in_rate = 31950;
|
||||||
|
// Input samplerate from libSNES.
|
||||||
|
// Lower this if you are experiencing frequent audio dropouts and vsync is enabled.
|
||||||
|
|
||||||
// Keybinds
|
// Keybinds
|
||||||
static const struct snes_keybind snes_keybinds[] = {
|
static const struct snes_keybind snes_keybinds[] = {
|
||||||
{ SNES_DEVICE_ID_JOYPAD_A, 'X', 1 },
|
{ SNES_DEVICE_ID_JOYPAD_A, 'X', 1 },
|
||||||
|
88
ssnes.c
88
ssnes.c
@ -1,4 +1,5 @@
|
|||||||
#include <GL/glfw.h>
|
#include <GL/glfw.h>
|
||||||
|
#include <samplerate.h>
|
||||||
#include "libsnes.hpp"
|
#include "libsnes.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -7,7 +8,17 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
///// RSound
|
///// RSound
|
||||||
static rsound_t *rd;
|
static rsound_t *rd = NULL;
|
||||||
|
static void audio_write(const void *data, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
///// samplerate
|
||||||
|
static SRC_STATE* source = NULL;
|
||||||
|
static float *src_input = NULL;
|
||||||
|
static float *src_output = NULL;
|
||||||
|
static size_t src_input_size = 0;
|
||||||
|
static size_t src_output_size = 0;
|
||||||
|
static size_t src_input_ptr = 0;
|
||||||
|
|
||||||
|
|
||||||
///// GL
|
///// GL
|
||||||
@ -16,6 +27,7 @@ static uint8_t* gl_buffer;
|
|||||||
static void GLFWCALL resize(int width, int height);
|
static void GLFWCALL resize(int width, int height);
|
||||||
static void init_gl(void);
|
static void init_gl(void);
|
||||||
static void uninit_gl(void);
|
static void uninit_gl(void);
|
||||||
|
static void uninit_audio(void);
|
||||||
|
|
||||||
static void uninit_gl(void)
|
static void uninit_gl(void)
|
||||||
{
|
{
|
||||||
@ -103,9 +115,9 @@ static void init_audio(void)
|
|||||||
{
|
{
|
||||||
rsd_init(&rd);
|
rsd_init(&rd);
|
||||||
int channels = 2;
|
int channels = 2;
|
||||||
int rate = 32000;
|
int rate = out_rate;
|
||||||
int format = RSD_S16_LE;
|
int format = RSD_S16_LE;
|
||||||
int latency = 64;
|
int latency = 80;
|
||||||
rsd_set_param(rd, RSD_CHANNELS, &channels);
|
rsd_set_param(rd, RSD_CHANNELS, &channels);
|
||||||
rsd_set_param(rd, RSD_SAMPLERATE, &rate);
|
rsd_set_param(rd, RSD_SAMPLERATE, &rate);
|
||||||
rsd_set_param(rd, RSD_FORMAT, &format);
|
rsd_set_param(rd, RSD_FORMAT, &format);
|
||||||
@ -115,12 +127,38 @@ static void init_audio(void)
|
|||||||
fprintf(stderr, "FAILED TO START RSD\n");
|
fprintf(stderr, "FAILED TO START RSD\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int err;
|
||||||
|
source = src_new(SRC_SINC_MEDIUM_QUALITY, 2, &err);
|
||||||
|
if ( source == NULL )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Couldn't init libsamplerate\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
src_set_ratio(source, (double)out_rate / (double)in_rate);
|
||||||
|
|
||||||
|
src_input_size = in_rate * 2 * sizeof(float) / 100;
|
||||||
|
src_output_size = out_rate * 2 * sizeof(float) / 100;
|
||||||
|
src_input = malloc ( src_input_size );
|
||||||
|
src_output = malloc ( src_output_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uninit_audio(void)
|
static void uninit_audio(void)
|
||||||
{
|
{
|
||||||
rsd_stop(rd);
|
if ( rd )
|
||||||
rsd_free(rd);
|
{
|
||||||
|
rsd_stop(rd);
|
||||||
|
rsd_free(rd);
|
||||||
|
rd = NULL;
|
||||||
|
}
|
||||||
|
if ( source )
|
||||||
|
{
|
||||||
|
src_delete(source);
|
||||||
|
source = NULL;
|
||||||
|
}
|
||||||
|
free (src_input); src_input = NULL;
|
||||||
|
free (src_output); src_output = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void video_refresh_GL(const uint16_t* data, unsigned width, unsigned height)
|
static void video_refresh_GL(const uint16_t* data, unsigned width, unsigned height)
|
||||||
@ -176,16 +214,46 @@ static void video_refresh_GL(const uint16_t* data, unsigned width, unsigned heig
|
|||||||
|
|
||||||
static void audio_refresh(uint16_t left, uint16_t right)
|
static void audio_refresh(uint16_t left, uint16_t right)
|
||||||
{
|
{
|
||||||
uint16_t samples[2] = {left, right};
|
src_input[src_input_ptr++] = (float)left;
|
||||||
|
src_input[src_input_ptr++] = (float)right;
|
||||||
|
|
||||||
|
SRC_DATA data;
|
||||||
|
|
||||||
|
if ( src_input_ptr == src_input_size )
|
||||||
|
{
|
||||||
|
data.input_frames = src_input_ptr / 4;
|
||||||
|
data.output_frames = src_output_size / 4;
|
||||||
|
data.data_in = src_input;
|
||||||
|
data.data_out = src_output;
|
||||||
|
data.src_ratio = (double)out_rate / (double)in_rate;
|
||||||
|
|
||||||
|
src_process(source, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(src_input, (uint32_t*)src_input + data.input_frames_used, src_input_size - data.input_frames_used * 4);
|
||||||
|
|
||||||
|
uint16_t outdata[data.output_frames_gen * 2];
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for ( i = 0; i < data.output_frames_gen * 2; i++ )
|
||||||
|
{
|
||||||
|
outdata[i] = (uint16_t)src_output[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_write(outdata, data.output_frames_gen * 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void audio_write(const void* data, size_t size)
|
||||||
|
{
|
||||||
rsd_delay_wait(rd);
|
rsd_delay_wait(rd);
|
||||||
if ( rsd_write(rd, samples, 4) < 4 )
|
if ( rsd_write(rd, data, size) == 0 )
|
||||||
fprintf(stderr, "WTF!!\n");
|
fprintf(stderr, "WTF!!\n");
|
||||||
|
|
||||||
if ( rsd_delay_ms(rd) < 32 )
|
if ( rsd_delay_ms(rd) < 40 )
|
||||||
{
|
{
|
||||||
int ms = 32;
|
int ms = 30;
|
||||||
size_t size = (ms * 32000 * 4) / 1000;
|
size_t size = (ms * out_rate * 4) / 1000;
|
||||||
void *temp = calloc(1, size);
|
void *temp = calloc(1, size);
|
||||||
rsd_write(rd, temp, size);
|
rsd_write(rd, temp, size);
|
||||||
free(temp);
|
free(temp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user