mirror of https://github.com/snes9xgit/snes9x.git
Gtk: Clean up a couple sound drivers.
Make them more idiomatic C++.
This commit is contained in:
parent
0a94eaa6dc
commit
a8fafcd94c
|
@ -13,16 +13,10 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
static void alsa_samples_available(void *data)
|
|
||||||
{
|
|
||||||
((S9xAlsaSoundDriver *)data)->samples_available();
|
|
||||||
}
|
|
||||||
|
|
||||||
S9xAlsaSoundDriver::S9xAlsaSoundDriver()
|
S9xAlsaSoundDriver::S9xAlsaSoundDriver()
|
||||||
{
|
{
|
||||||
pcm = NULL;
|
pcm = {};
|
||||||
sound_buffer = NULL;
|
sound_buffer.clear();
|
||||||
sound_buffer_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xAlsaSoundDriver::init()
|
void S9xAlsaSoundDriver::init()
|
||||||
|
@ -33,20 +27,16 @@ void S9xAlsaSoundDriver::terminate()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
S9xSetSamplesAvailableCallback(NULL, NULL);
|
S9xSetSamplesAvailableCallback(nullptr, nullptr);
|
||||||
|
|
||||||
if (pcm)
|
if (pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_drain(pcm);
|
snd_pcm_drain(pcm);
|
||||||
snd_pcm_close(pcm);
|
snd_pcm_close(pcm);
|
||||||
pcm = NULL;
|
pcm = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sound_buffer)
|
sound_buffer.clear();
|
||||||
{
|
|
||||||
free(sound_buffer);
|
|
||||||
sound_buffer = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xAlsaSoundDriver::start()
|
void S9xAlsaSoundDriver::start()
|
||||||
|
@ -71,10 +61,7 @@ bool S9xAlsaSoundDriver::open_device()
|
||||||
printf("ALSA sound driver initializing...\n");
|
printf("ALSA sound driver initializing...\n");
|
||||||
printf(" --> (Device: default)...\n");
|
printf(" --> (Device: default)...\n");
|
||||||
|
|
||||||
err = snd_pcm_open(&pcm,
|
err = snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||||
"default",
|
|
||||||
SND_PCM_STREAM_PLAYBACK,
|
|
||||||
SND_PCM_NONBLOCK);
|
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
{
|
{
|
||||||
|
@ -92,34 +79,34 @@ bool S9xAlsaSoundDriver::open_device()
|
||||||
snd_pcm_hw_params_set_rate_resample(pcm, hw_params, 0);
|
snd_pcm_hw_params_set_rate_resample(pcm, hw_params, 0);
|
||||||
snd_pcm_hw_params_set_channels(pcm, hw_params, 2);
|
snd_pcm_hw_params_set_channels(pcm, hw_params, 2);
|
||||||
|
|
||||||
snd_pcm_hw_params_get_rate_min(hw_params, &min, NULL);
|
snd_pcm_hw_params_get_rate_min(hw_params, &min, nullptr);
|
||||||
snd_pcm_hw_params_get_rate_max(hw_params, &max, NULL);
|
snd_pcm_hw_params_get_rate_max(hw_params, &max, nullptr);
|
||||||
printf(" --> Available rates: %d to %d\n", min, max);
|
printf(" --> Available rates: %d to %d\n", min, max);
|
||||||
if (Settings.SoundPlaybackRate > max && Settings.SoundPlaybackRate < min)
|
if (Settings.SoundPlaybackRate > max && Settings.SoundPlaybackRate < min)
|
||||||
{
|
{
|
||||||
printf(" Rate %d not available. Using %d instead.\n", Settings.SoundPlaybackRate, max);
|
printf(" Rate %d not available. Using %d instead.\n", Settings.SoundPlaybackRate, max);
|
||||||
Settings.SoundPlaybackRate = max;
|
Settings.SoundPlaybackRate = max;
|
||||||
}
|
}
|
||||||
snd_pcm_hw_params_set_rate_near(pcm, hw_params, &Settings.SoundPlaybackRate, NULL);
|
snd_pcm_hw_params_set_rate_near(pcm, hw_params, &Settings.SoundPlaybackRate, nullptr);
|
||||||
|
|
||||||
snd_pcm_hw_params_get_buffer_time_min(hw_params, &min, NULL);
|
snd_pcm_hw_params_get_buffer_time_min(hw_params, &min, nullptr);
|
||||||
snd_pcm_hw_params_get_buffer_time_max(hw_params, &max, NULL);
|
snd_pcm_hw_params_get_buffer_time_max(hw_params, &max, nullptr);
|
||||||
printf(" --> Available buffer sizes: %dms to %dms\n", min / 1000, max / 1000);
|
printf(" --> Available buffer sizes: %dms to %dms\n", min / 1000, max / 1000);
|
||||||
if (buffer_size < min && buffer_size > max)
|
if (buffer_size < min && buffer_size > max)
|
||||||
{
|
{
|
||||||
printf(" Buffer size %dms not available. Using %d instead.\n", buffer_size / 1000, (min + max) / 2000);
|
printf(" Buffer size %dms not available. Using %d instead.\n", buffer_size / 1000, (min + max) / 2000);
|
||||||
buffer_size = (min + max) / 2;
|
buffer_size = (min + max) / 2;
|
||||||
}
|
}
|
||||||
snd_pcm_hw_params_set_buffer_time_near(pcm, hw_params, &buffer_size, NULL);
|
snd_pcm_hw_params_set_buffer_time_near(pcm, hw_params, &buffer_size, nullptr);
|
||||||
|
|
||||||
snd_pcm_hw_params_get_periods_min(hw_params, &min, NULL);
|
snd_pcm_hw_params_get_periods_min(hw_params, &min, nullptr);
|
||||||
snd_pcm_hw_params_get_periods_max(hw_params, &max, NULL);
|
snd_pcm_hw_params_get_periods_max(hw_params, &max, nullptr);
|
||||||
printf(" --> Period ranges: %d to %d blocks\n", min, max);
|
printf(" --> Period ranges: %d to %d blocks\n", min, max);
|
||||||
if (periods > max)
|
if (periods > max)
|
||||||
{
|
{
|
||||||
periods = max;
|
periods = max;
|
||||||
}
|
}
|
||||||
snd_pcm_hw_params_set_periods_near(pcm, hw_params, &periods, NULL);
|
snd_pcm_hw_params_set_periods_near(pcm, hw_params, &periods, nullptr);
|
||||||
|
|
||||||
if ((err = snd_pcm_hw_params(pcm, hw_params)) < 0)
|
if ((err = snd_pcm_hw_params(pcm, hw_params)) < 0)
|
||||||
{
|
{
|
||||||
|
@ -144,14 +131,16 @@ bool S9xAlsaSoundDriver::open_device()
|
||||||
|
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
|
|
||||||
S9xSetSamplesAvailableCallback(alsa_samples_available, this);
|
S9xSetSamplesAvailableCallback([](void *userdata) {
|
||||||
|
((decltype(this)) userdata)->samples_available();;
|
||||||
|
}, this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
close_fail:
|
close_fail:
|
||||||
snd_pcm_drain(pcm);
|
snd_pcm_drain(pcm);
|
||||||
snd_pcm_close(pcm);
|
snd_pcm_close(pcm);
|
||||||
pcm = NULL;
|
pcm = nullptr;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
printf("Failed: %s\n", snd_strerror(err));
|
printf("Failed: %s\n", snd_strerror(err));
|
||||||
|
@ -162,7 +151,7 @@ fail:
|
||||||
void S9xAlsaSoundDriver::samples_available()
|
void S9xAlsaSoundDriver::samples_available()
|
||||||
{
|
{
|
||||||
snd_pcm_sframes_t frames_written, frames;
|
snd_pcm_sframes_t frames_written, frames;
|
||||||
int bytes;
|
size_t bytes;
|
||||||
|
|
||||||
frames = snd_pcm_avail(pcm);
|
frames = snd_pcm_avail(pcm);
|
||||||
|
|
||||||
|
@ -206,13 +195,10 @@ void S9xAlsaSoundDriver::samples_available()
|
||||||
if (bytes <= 0)
|
if (bytes <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sound_buffer_size < bytes || sound_buffer == NULL)
|
if (sound_buffer.size() < bytes)
|
||||||
{
|
sound_buffer.resize(bytes);
|
||||||
sound_buffer = (uint8 *)realloc(sound_buffer, bytes);
|
|
||||||
sound_buffer_size = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
S9xMixSamples(sound_buffer, frames * 2);
|
S9xMixSamples(sound_buffer.data(), frames * 2);
|
||||||
|
|
||||||
frames_written = 0;
|
frames_written = 0;
|
||||||
|
|
||||||
|
@ -221,8 +207,7 @@ void S9xAlsaSoundDriver::samples_available()
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
result = snd_pcm_writei(pcm,
|
result = snd_pcm_writei(pcm,
|
||||||
sound_buffer +
|
&sound_buffer[snd_pcm_frames_to_bytes(pcm, frames_written)],
|
||||||
snd_pcm_frames_to_bytes(pcm, frames_written),
|
|
||||||
frames - frames_written);
|
frames - frames_written);
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
|
|
|
@ -24,8 +24,7 @@ class S9xAlsaSoundDriver : public S9xSoundDriver
|
||||||
|
|
||||||
private:
|
private:
|
||||||
snd_pcm_t *pcm;
|
snd_pcm_t *pcm;
|
||||||
int sound_buffer_size;
|
std::vector<uint8_t> sound_buffer;
|
||||||
uint8 *sound_buffer;
|
|
||||||
int output_buffer_size;
|
int output_buffer_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,26 +13,22 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
static void pulse_samples_available(void *data)
|
|
||||||
{
|
|
||||||
((S9xPulseSoundDriver *)data)->samples_available();
|
|
||||||
}
|
|
||||||
|
|
||||||
S9xPulseSoundDriver::S9xPulseSoundDriver()
|
S9xPulseSoundDriver::S9xPulseSoundDriver()
|
||||||
{
|
{
|
||||||
mainloop = NULL;
|
init();
|
||||||
context = NULL;
|
|
||||||
stream = NULL;
|
|
||||||
buffer_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xPulseSoundDriver::init()
|
void S9xPulseSoundDriver::init()
|
||||||
{
|
{
|
||||||
|
mainloop = {};
|
||||||
|
context = {};
|
||||||
|
stream = {};
|
||||||
|
buffer_size = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xPulseSoundDriver::terminate()
|
void S9xPulseSoundDriver::terminate()
|
||||||
{
|
{
|
||||||
S9xSetSamplesAvailableCallback(NULL, NULL);
|
S9xSetSamplesAvailableCallback(nullptr, nullptr);
|
||||||
|
|
||||||
if (mainloop)
|
if (mainloop)
|
||||||
pa_threaded_mainloop_stop(mainloop);
|
pa_threaded_mainloop_stop(mainloop);
|
||||||
|
@ -110,15 +106,14 @@ static void stream_state_callback(pa_stream *p, void *userdata)
|
||||||
|
|
||||||
bool S9xPulseSoundDriver::open_device()
|
bool S9xPulseSoundDriver::open_device()
|
||||||
{
|
{
|
||||||
int err = PA_ERR_UNKNOWN;
|
init();
|
||||||
pa_sample_spec ss;
|
|
||||||
pa_buffer_attr buffer_attr;
|
|
||||||
const pa_buffer_attr *actual_buffer_attr;
|
|
||||||
|
|
||||||
|
pa_sample_spec ss;
|
||||||
ss.channels = 2;
|
ss.channels = 2;
|
||||||
ss.format = PA_SAMPLE_S16NE;
|
ss.format = PA_SAMPLE_S16NE;
|
||||||
ss.rate = Settings.SoundPlaybackRate;
|
ss.rate = Settings.SoundPlaybackRate;
|
||||||
|
|
||||||
|
pa_buffer_attr buffer_attr;
|
||||||
buffer_attr.fragsize = -1;
|
buffer_attr.fragsize = -1;
|
||||||
buffer_attr.tlength = pa_usec_to_bytes(gui_config->sound_buffer_size * 1000, &ss);
|
buffer_attr.tlength = pa_usec_to_bytes(gui_config->sound_buffer_size * 1000, &ss);
|
||||||
buffer_attr.maxlength = buffer_attr.tlength * 2;
|
buffer_attr.maxlength = buffer_attr.tlength * 2;
|
||||||
|
@ -130,93 +125,59 @@ bool S9xPulseSoundDriver::open_device()
|
||||||
printf(" --> (%dhz, 16-bit Stereo, %dms)...",
|
printf(" --> (%dhz, 16-bit Stereo, %dms)...",
|
||||||
Settings.SoundPlaybackRate,
|
Settings.SoundPlaybackRate,
|
||||||
gui_config->sound_buffer_size);
|
gui_config->sound_buffer_size);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
|
int err = PA_ERR_UNKNOWN;
|
||||||
mainloop = pa_threaded_mainloop_new();
|
mainloop = pa_threaded_mainloop_new();
|
||||||
if (!mainloop)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed to create mainloop.\n");
|
|
||||||
goto error0;
|
|
||||||
}
|
|
||||||
|
|
||||||
context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Snes9x");
|
context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Snes9x");
|
||||||
if (!context)
|
|
||||||
goto error1;
|
|
||||||
|
|
||||||
pa_context_set_state_callback(context, context_state_cb, this);
|
pa_context_set_state_callback(context, context_state_cb, this);
|
||||||
if ((err = pa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL)) != 0)
|
pa_context_connect(context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
|
||||||
goto error2;
|
|
||||||
|
|
||||||
lock();
|
lock();
|
||||||
|
pa_threaded_mainloop_start(mainloop);
|
||||||
if ((err = pa_threaded_mainloop_start(mainloop)) != 0)
|
|
||||||
goto error2;
|
|
||||||
wait();
|
wait();
|
||||||
|
|
||||||
if ((err = pa_context_get_state(context)) != PA_CONTEXT_READY)
|
if ((err = pa_context_get_state(context)) != PA_CONTEXT_READY)
|
||||||
{
|
return false;
|
||||||
printf("Coundn't create context: State: %d\n", err);
|
|
||||||
goto error2;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream = pa_stream_new(context, "Game", &ss, NULL);
|
stream = pa_stream_new(context, "Game", &ss, nullptr);
|
||||||
|
|
||||||
if (!stream)
|
|
||||||
goto error2;
|
|
||||||
|
|
||||||
pa_stream_set_state_callback(stream, stream_state_callback, this);
|
pa_stream_set_state_callback(stream, stream_state_callback, this);
|
||||||
|
|
||||||
if (pa_stream_connect_playback(stream,
|
if (pa_stream_connect_playback(stream,
|
||||||
NULL,
|
nullptr,
|
||||||
&buffer_attr,
|
&buffer_attr,
|
||||||
PA_STREAM_ADJUST_LATENCY,
|
PA_STREAM_ADJUST_LATENCY,
|
||||||
NULL,
|
nullptr,
|
||||||
NULL) < 0)
|
nullptr) < 0)
|
||||||
goto error3;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
wait();
|
wait();
|
||||||
|
|
||||||
if (pa_stream_get_state(stream) != PA_STREAM_READY)
|
if (pa_stream_get_state(stream) != PA_STREAM_READY)
|
||||||
{
|
return false;
|
||||||
goto error3;
|
|
||||||
}
|
|
||||||
|
|
||||||
actual_buffer_attr = pa_stream_get_buffer_attr(stream);
|
auto actual_buffer_attr = pa_stream_get_buffer_attr(stream);
|
||||||
|
unlock();
|
||||||
|
|
||||||
buffer_size = actual_buffer_attr->tlength;
|
buffer_size = actual_buffer_attr->tlength;
|
||||||
|
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
|
|
||||||
S9xSetSamplesAvailableCallback(pulse_samples_available, this);
|
S9xSetSamplesAvailableCallback([](void *userdata) {
|
||||||
|
((decltype(this)) userdata)->samples_available();;
|
||||||
|
}, this);
|
||||||
|
|
||||||
unlock();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error3:
|
|
||||||
pa_stream_disconnect(stream);
|
|
||||||
pa_stream_unref(stream);
|
|
||||||
error2:
|
|
||||||
pa_context_disconnect(context);
|
|
||||||
pa_context_unref(context);
|
|
||||||
unlock();
|
|
||||||
error1:
|
|
||||||
pa_threaded_mainloop_free(mainloop);
|
|
||||||
error0:
|
|
||||||
printf("Failed: %s\n", pa_strerror(err));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xPulseSoundDriver::samples_available()
|
void S9xPulseSoundDriver::samples_available()
|
||||||
{
|
{
|
||||||
size_t bytes;
|
|
||||||
int samples;
|
|
||||||
const pa_buffer_attr *buffer_attr;
|
|
||||||
void *output_buffer = NULL;
|
|
||||||
|
|
||||||
lock();
|
lock();
|
||||||
bytes = pa_stream_writable_size(stream);
|
size_t bytes = pa_stream_writable_size(stream);
|
||||||
buffer_attr = pa_stream_get_buffer_attr(stream);
|
auto buffer_attr = pa_stream_get_buffer_attr(stream);
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
buffer_size = buffer_attr->tlength;
|
buffer_size = buffer_attr->tlength;
|
||||||
|
@ -226,22 +187,22 @@ void S9xPulseSoundDriver::samples_available()
|
||||||
S9xUpdateDynamicRate(bytes, buffer_size);
|
S9xUpdateDynamicRate(bytes, buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
samples = S9xGetSampleCount();
|
size_t samples = S9xGetSampleCount();
|
||||||
|
|
||||||
if (Settings.DynamicRateControl && !Settings.SoundSync)
|
int frames_available = samples / 2;
|
||||||
|
int frames_writable = bytes / 4;
|
||||||
|
|
||||||
|
if (frames_writable < frames_available)
|
||||||
{
|
{
|
||||||
if ((int)bytes < (samples * 2))
|
if (Settings.DynamicRateControl && !Settings.SoundSync)
|
||||||
{
|
{
|
||||||
S9xClearSamples();
|
S9xClearSamples();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Settings.SoundSync && !Settings.TurboMode && !Settings.Mute)
|
if (Settings.SoundSync && !Settings.TurboMode && !Settings.Mute)
|
||||||
{
|
|
||||||
if ((int)bytes < samples * 2)
|
|
||||||
{
|
{
|
||||||
int usec_to_sleep = ((samples >> 1) - (bytes >> 2)) * 10000 /
|
int usec_to_sleep = (frames_available - frames_writable) * 10000 /
|
||||||
(Settings.SoundPlaybackRate / 100);
|
(Settings.SoundPlaybackRate / 100);
|
||||||
usleep(usec_to_sleep > 0 ? usec_to_sleep : 0);
|
usleep(usec_to_sleep > 0 ? usec_to_sleep : 0);
|
||||||
lock();
|
lock();
|
||||||
|
@ -250,16 +211,17 @@ void S9xPulseSoundDriver::samples_available()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes = MIN((int)bytes, samples * 2) & ~1;
|
bytes = MIN(bytes, samples * 2) & ~1;
|
||||||
|
|
||||||
if (!bytes)
|
if (!bytes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
|
void *output_buffer;;
|
||||||
if (pa_stream_begin_write(stream, &output_buffer, &bytes) != 0)
|
if (pa_stream_begin_write(stream, &output_buffer, &bytes) != 0)
|
||||||
{
|
{
|
||||||
pa_stream_flush(stream, NULL, NULL);
|
pa_stream_flush(stream, nullptr, nullptr);
|
||||||
unlock();
|
unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -270,8 +232,8 @@ void S9xPulseSoundDriver::samples_available()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
S9xMixSamples((uint8 *)output_buffer, bytes >> 1);
|
S9xMixSamples((uint8_t *)output_buffer, bytes >> 1);
|
||||||
pa_stream_write(stream, output_buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
|
pa_stream_write(stream, output_buffer, bytes, nullptr, 0, PA_SEEK_RELATIVE);
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,16 +9,6 @@
|
||||||
#include "apu/apu.h"
|
#include "apu/apu.h"
|
||||||
#include "snes9x.h"
|
#include "snes9x.h"
|
||||||
|
|
||||||
static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
|
|
||||||
{
|
|
||||||
((S9xSDLSoundDriver *)userdata)->mix((unsigned char *)stream, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void c_samples_available(void *data)
|
|
||||||
{
|
|
||||||
((S9xSDLSoundDriver *)data)->samples_available();
|
|
||||||
}
|
|
||||||
|
|
||||||
void S9xSDLSoundDriver::samples_available()
|
void S9xSDLSoundDriver::samples_available()
|
||||||
{
|
{
|
||||||
int snes_samples_available = S9xGetSampleCount();
|
int snes_samples_available = S9xGetSampleCount();
|
||||||
|
@ -89,7 +79,10 @@ bool S9xSDLSoundDriver::open_device()
|
||||||
audiospec.channels = 2;
|
audiospec.channels = 2;
|
||||||
audiospec.format = AUDIO_S16SYS;
|
audiospec.format = AUDIO_S16SYS;
|
||||||
audiospec.samples = (gui_config->sound_buffer_size * audiospec.freq / 1000) >> 2;
|
audiospec.samples = (gui_config->sound_buffer_size * audiospec.freq / 1000) >> 2;
|
||||||
audiospec.callback = sdl_audio_callback;
|
audiospec.callback = [](void *userdata, uint8_t *stream, int len) {
|
||||||
|
((S9xSDLSoundDriver *)userdata)->mix((unsigned char *)stream, len);
|
||||||
|
};
|
||||||
|
|
||||||
audiospec.userdata = this;
|
audiospec.userdata = this;
|
||||||
|
|
||||||
printf("SDL sound driver initializing...\n");
|
printf("SDL sound driver initializing...\n");
|
||||||
|
@ -106,9 +99,10 @@ bool S9xSDLSoundDriver::open_device()
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
|
|
||||||
buffer.resize(gui_config->sound_buffer_size * audiospec.freq / 500);
|
buffer.resize(gui_config->sound_buffer_size * audiospec.freq / 500);
|
||||||
buffer.time_ratio(1.0);
|
|
||||||
|
|
||||||
S9xSetSamplesAvailableCallback(c_samples_available, this);
|
S9xSetSamplesAvailableCallback([](void *userdata) {
|
||||||
|
((decltype(this)) userdata)->samples_available();;
|
||||||
|
}, this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue