mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2024-06-22 06:02:26 -04:00
Use SDL's internal sample rate converter instead of libsamplerate
This commit is contained in:
parent
8148da0b3e
commit
6c5f60592e
|
@ -13,13 +13,11 @@ nestopia_CPPFLAGS = \
|
||||||
-DNST_PRAGMA_ONCE \
|
-DNST_PRAGMA_ONCE \
|
||||||
$(ZLIB_CFLAGS) \
|
$(ZLIB_CFLAGS) \
|
||||||
$(LIBARCHIVE_CFLAGS) \
|
$(LIBARCHIVE_CFLAGS) \
|
||||||
$(SAMPLERATE_CFLAGS) \
|
|
||||||
$(SDL2_CFLAGS) \
|
$(SDL2_CFLAGS) \
|
||||||
$(FLTK_CFLAGS)
|
$(FLTK_CFLAGS)
|
||||||
nestopia_LDADD = \
|
nestopia_LDADD = \
|
||||||
$(ZLIB_LIBS) \
|
$(ZLIB_LIBS) \
|
||||||
$(LIBARCHIVE_LIBS) \
|
$(LIBARCHIVE_LIBS) \
|
||||||
$(SAMPLERATE_LIBS) \
|
|
||||||
$(SDL2_LIBS) \
|
$(SDL2_LIBS) \
|
||||||
$(FLTK_LIBS)
|
$(FLTK_LIBS)
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,12 @@ libretro community. For libretro-specific issues, please use the libretro reposi
|
||||||
https://github.com/libretro/nestopia
|
https://github.com/libretro/nestopia
|
||||||
|
|
||||||
This project depends on the following libraries:
|
This project depends on the following libraries:
|
||||||
FLTK 1.3, SDL2, libarchive, libsamplerate, zlib
|
FLTK 1.3, SDL2, libarchive, zlib
|
||||||
|
|
||||||
## Installing Dependencies
|
## Installing Dependencies
|
||||||
Install dependencies required for building on Debian-based Linux distributions:
|
Install dependencies required for building on Debian-based Linux distributions:
|
||||||
```
|
```
|
||||||
apt-get install build-essential autoconf autoconf-archive automake autotools-dev libarchive-dev libfltk1.3-dev libsamplerate0-dev libsdl2-dev zlib1g-dev
|
apt-get install build-essential autoconf autoconf-archive automake autotools-dev libfltk1.3-dev libsdl2-dev libarchive-dev zlib1g-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## FLTK Build
|
## FLTK Build
|
||||||
|
|
|
@ -76,9 +76,6 @@ PKG_CHECK_MODULES([LIBARCHIVE], [libarchive])
|
||||||
dnl SDL2
|
dnl SDL2
|
||||||
PKG_CHECK_MODULES([SDL2], [sdl2])
|
PKG_CHECK_MODULES([SDL2], [sdl2])
|
||||||
|
|
||||||
dnl SAMPLERATE
|
|
||||||
PKG_CHECK_MODULES([SAMPLERATE], [samplerate])
|
|
||||||
|
|
||||||
AC_CHECK_PROG(FLTKCONFIG,fltk-config,[fltk-config],[no])
|
AC_CHECK_PROG(FLTKCONFIG,fltk-config,[fltk-config],[no])
|
||||||
test "$FLTKCONFIG" == "no" && AC_MSG_ERROR([Cannot find the fltk-config executable. Is FLTK installed?])
|
test "$FLTKCONFIG" == "no" && AC_MSG_ERROR([Cannot find the fltk-config executable. Is FLTK installed?])
|
||||||
|
|
||||||
|
|
|
@ -23,29 +23,20 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <samplerate.h>
|
|
||||||
|
|
||||||
#include "nstcommon.h"
|
#include "nstcommon.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
#define IBUFSIZE 4800
|
#define BUFSIZE 16000
|
||||||
#define EBUFSIZE 12800
|
|
||||||
|
|
||||||
extern Emulator emulator;
|
extern Emulator emulator;
|
||||||
|
|
||||||
static SDL_AudioSpec spec, obtained;
|
static SDL_AudioSpec spec, obtained;
|
||||||
static SDL_AudioDeviceID dev;
|
static SDL_AudioDeviceID dev;
|
||||||
|
static SDL_AudioCVT cvt;
|
||||||
|
|
||||||
static SRC_STATE *srcstate = nullptr;
|
static int16_t intbuf[BUFSIZE];
|
||||||
static SRC_DATA srcdata;
|
static int16_t extbuf[BUFSIZE];
|
||||||
|
|
||||||
static int16_t intbuf[IBUFSIZE];
|
|
||||||
|
|
||||||
static float fltbuf_in[IBUFSIZE];
|
|
||||||
static float fltbuf_out[IBUFSIZE];
|
|
||||||
|
|
||||||
static float extbuf[EBUFSIZE];
|
|
||||||
static uint16_t bufstart = 0;
|
static uint16_t bufstart = 0;
|
||||||
static uint16_t bufend = 0;
|
static uint16_t bufend = 0;
|
||||||
static uint16_t bufsamples = 0;
|
static uint16_t bufsamples = 0;
|
||||||
|
@ -59,31 +50,21 @@ void audio_set_speed(int speed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queue() {
|
void audio_queue() {
|
||||||
while ((bufsamples + bufsize) >= EBUFSIZE) { SDL_Delay(1); }
|
while ((bufsamples + bufsize) >= BUFSIZE) { SDL_Delay(1); }
|
||||||
|
|
||||||
SDL_LockAudioDevice(dev);
|
SDL_LockAudioDevice(dev);
|
||||||
|
int numsamples = bufsize;
|
||||||
|
|
||||||
src_short_to_float_array(intbuf, fltbuf_in, bufsize);
|
if (bufsamples < bufsize * 3) {
|
||||||
|
SDL_ConvertAudio(&cvt);
|
||||||
srcdata.input_frames = bufsize / channels;
|
numsamples += channels;
|
||||||
srcdata.end_of_input = 0;
|
|
||||||
|
|
||||||
if (bufsamples < bufsize * 2) {
|
|
||||||
srcdata.output_frames = bufsize / channels + 1;
|
|
||||||
srcdata.src_ratio = (conf.audio_sample_rate + 60) / (conf.audio_sample_rate * 1.0);
|
|
||||||
}
|
|
||||||
else if (bufsamples > bufsize * 3) {
|
|
||||||
srcdata.output_frames = bufsize / channels;
|
|
||||||
srcdata.src_ratio = 1.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src_process(srcstate, &srcdata);
|
for (int i = 0; i < numsamples; i++) {
|
||||||
|
extbuf[bufend] = intbuf[i];
|
||||||
for (int i = 0; i < srcdata.output_frames_gen * channels; i++) {
|
bufend = (bufend + 1) % BUFSIZE;
|
||||||
extbuf[bufend] = fltbuf_out[i];
|
|
||||||
bufend = (bufend + 1) % EBUFSIZE;
|
|
||||||
bufsamples++;
|
bufsamples++;
|
||||||
if (bufsamples >= EBUFSIZE - 1) { break; }
|
if (bufsamples >= BUFSIZE - 1) { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockAudioDevice(dev);
|
SDL_UnlockAudioDevice(dev);
|
||||||
|
@ -91,27 +72,29 @@ void audio_queue() {
|
||||||
|
|
||||||
static inline float audio_dequeue() {
|
static inline float audio_dequeue() {
|
||||||
if (bufsamples == 0) { return 0; }
|
if (bufsamples == 0) { return 0; }
|
||||||
float sample = extbuf[bufstart];
|
int16_t sample = extbuf[bufstart];
|
||||||
bufstart = (bufstart + 1) % EBUFSIZE;
|
bufstart = (bufstart + 1) % BUFSIZE;
|
||||||
bufsamples--;
|
bufsamples--;
|
||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_cb(void *data, uint8_t *stream, int len) {
|
void audio_cb(void *data, uint8_t *stream, int len) {
|
||||||
float *out = (float*)stream;
|
int16_t *out = (int16_t*)stream;
|
||||||
for (int i = 0; i < len / sizeof(float); i++) {
|
for (int i = 0; i < len / sizeof(int16_t); i++) {
|
||||||
out[i] = audio_dequeue();
|
out[i] = audio_dequeue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_deinit() {
|
void audio_deinit() {
|
||||||
if (dev) { SDL_CloseAudioDevice(dev); }
|
if (dev) { SDL_CloseAudioDevice(dev); }
|
||||||
if (srcstate) { src_delete(srcstate); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_init_sdl() {
|
void audio_init_sdl() {
|
||||||
|
int e = 1; // Check Endianness
|
||||||
|
SDL_AudioFormat fmt = ((int)*((unsigned char *)&e) == 1) ? AUDIO_S16LSB : AUDIO_S16MSB;
|
||||||
|
|
||||||
spec.freq = conf.audio_sample_rate;
|
spec.freq = conf.audio_sample_rate;
|
||||||
spec.format = AUDIO_F32SYS;
|
spec.format = fmt;
|
||||||
spec.channels = channels;
|
spec.channels = channels;
|
||||||
spec.silence = 0;
|
spec.silence = 0;
|
||||||
spec.samples = 512;
|
spec.samples = 512;
|
||||||
|
@ -119,13 +102,7 @@ void audio_init_sdl() {
|
||||||
spec.callback = audio_cb;
|
spec.callback = audio_cb;
|
||||||
|
|
||||||
bufsize = channels * (conf.audio_sample_rate / framerate);
|
bufsize = channels * (conf.audio_sample_rate / framerate);
|
||||||
|
bufend = bufstart = bufsamples = 0;
|
||||||
int err;
|
|
||||||
srcstate = src_new(SRC_SINC_FASTEST, channels, &err);
|
|
||||||
srcdata.data_in = fltbuf_in;
|
|
||||||
srcdata.data_out = fltbuf_out;
|
|
||||||
srcdata.output_frames = bufsize / channels;
|
|
||||||
srcdata.src_ratio = 1.0;
|
|
||||||
|
|
||||||
dev = SDL_OpenAudioDevice(NULL, 0, &spec, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
|
dev = SDL_OpenAudioDevice(NULL, 0, &spec, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
|
@ -135,6 +112,11 @@ void audio_init_sdl() {
|
||||||
fprintf(stderr, "Audio: SDL - %dHz, %d channel(s)\n", spec.freq, spec.channels);
|
fprintf(stderr, "Audio: SDL - %dHz, %d channel(s)\n", spec.freq, spec.channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_BuildAudioCVT(&cvt, fmt, channels, conf.audio_sample_rate, fmt, channels, conf.audio_sample_rate + ((nst_pal() ? 50 : 60) * channels));
|
||||||
|
SDL_assert(cvt.needed);
|
||||||
|
cvt.len = (bufsize + channels) * sizeof(int16_t);
|
||||||
|
cvt.buf = (Uint8*)intbuf;
|
||||||
|
|
||||||
SDL_PauseAudioDevice(dev, 1); // Setting to 0 unpauses
|
SDL_PauseAudioDevice(dev, 1); // Setting to 0 unpauses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,9 +125,7 @@ void audio_init() {
|
||||||
// Set the framerate based on the region. For PAL: (60 / 6) * 5 = 50
|
// Set the framerate based on the region. For PAL: (60 / 6) * 5 = 50
|
||||||
framerate = nst_pal() ? (conf.timing_speed / 6) * 5 : conf.timing_speed;
|
framerate = nst_pal() ? (conf.timing_speed / 6) * 5 : conf.timing_speed;
|
||||||
channels = conf.audio_stereo ? 2 : 1;
|
channels = conf.audio_stereo ? 2 : 1;
|
||||||
memset(intbuf, 0, sizeof(int16_t) * IBUFSIZE);
|
memset(intbuf, 0, sizeof(int16_t) * BUFSIZE);
|
||||||
memset(fltbuf_in, 0, sizeof(float) * IBUFSIZE);
|
|
||||||
memset(fltbuf_out, 0, sizeof(float) * IBUFSIZE);
|
|
||||||
audio_init_sdl();
|
audio_init_sdl();
|
||||||
paused = false;
|
paused = false;
|
||||||
}
|
}
|
||||||
|
@ -196,5 +176,5 @@ void audio_adj_volume() {
|
||||||
sound.SetVolume(Sound::CHANNEL_N163, conf.audio_vol_n163);
|
sound.SetVolume(Sound::CHANNEL_N163, conf.audio_vol_n163);
|
||||||
sound.SetVolume(Sound::CHANNEL_S5B, conf.audio_vol_s5b);
|
sound.SetVolume(Sound::CHANNEL_S5B, conf.audio_vol_s5b);
|
||||||
|
|
||||||
if (conf.audio_volume == 0) { memset(intbuf, 0, sizeof(intbuf)); }
|
if (conf.audio_volume == 0) { memset(intbuf, 0, sizeof(int16_t) * BUFSIZE); }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue