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/time.h>
|
||||
|
||||
static void alsa_samples_available(void *data)
|
||||
{
|
||||
((S9xAlsaSoundDriver *)data)->samples_available();
|
||||
}
|
||||
|
||||
S9xAlsaSoundDriver::S9xAlsaSoundDriver()
|
||||
{
|
||||
pcm = NULL;
|
||||
sound_buffer = NULL;
|
||||
sound_buffer_size = 0;
|
||||
pcm = {};
|
||||
sound_buffer.clear();
|
||||
}
|
||||
|
||||
void S9xAlsaSoundDriver::init()
|
||||
@ -33,20 +27,16 @@ void S9xAlsaSoundDriver::terminate()
|
||||
{
|
||||
stop();
|
||||
|
||||
S9xSetSamplesAvailableCallback(NULL, NULL);
|
||||
S9xSetSamplesAvailableCallback(nullptr, nullptr);
|
||||
|
||||
if (pcm)
|
||||
{
|
||||
snd_pcm_drain(pcm);
|
||||
snd_pcm_close(pcm);
|
||||
pcm = NULL;
|
||||
pcm = nullptr;
|
||||
}
|
||||
|
||||
if (sound_buffer)
|
||||
{
|
||||
free(sound_buffer);
|
||||
sound_buffer = NULL;
|
||||
}
|
||||
sound_buffer.clear();
|
||||
}
|
||||
|
||||
void S9xAlsaSoundDriver::start()
|
||||
@ -71,10 +61,7 @@ bool S9xAlsaSoundDriver::open_device()
|
||||
printf("ALSA sound driver initializing...\n");
|
||||
printf(" --> (Device: default)...\n");
|
||||
|
||||
err = snd_pcm_open(&pcm,
|
||||
"default",
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
SND_PCM_NONBLOCK);
|
||||
err = snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
|
||||
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_channels(pcm, hw_params, 2);
|
||||
|
||||
snd_pcm_hw_params_get_rate_min(hw_params, &min, NULL);
|
||||
snd_pcm_hw_params_get_rate_max(hw_params, &max, NULL);
|
||||
snd_pcm_hw_params_get_rate_min(hw_params, &min, nullptr);
|
||||
snd_pcm_hw_params_get_rate_max(hw_params, &max, nullptr);
|
||||
printf(" --> Available rates: %d to %d\n", min, max);
|
||||
if (Settings.SoundPlaybackRate > max && Settings.SoundPlaybackRate < min)
|
||||
{
|
||||
printf(" Rate %d not available. Using %d instead.\n", 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_max(hw_params, &max, NULL);
|
||||
snd_pcm_hw_params_get_buffer_time_min(hw_params, &min, nullptr);
|
||||
snd_pcm_hw_params_get_buffer_time_max(hw_params, &max, nullptr);
|
||||
printf(" --> Available buffer sizes: %dms to %dms\n", min / 1000, max / 1000);
|
||||
if (buffer_size < min && buffer_size > max)
|
||||
{
|
||||
printf(" Buffer size %dms not available. Using %d instead.\n", buffer_size / 1000, (min + max) / 2000);
|
||||
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_max(hw_params, &max, NULL);
|
||||
snd_pcm_hw_params_get_periods_min(hw_params, &min, nullptr);
|
||||
snd_pcm_hw_params_get_periods_max(hw_params, &max, nullptr);
|
||||
printf(" --> Period ranges: %d to %d blocks\n", min, max);
|
||||
if (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)
|
||||
{
|
||||
@ -144,14 +131,16 @@ bool S9xAlsaSoundDriver::open_device()
|
||||
|
||||
printf("OK\n");
|
||||
|
||||
S9xSetSamplesAvailableCallback(alsa_samples_available, this);
|
||||
S9xSetSamplesAvailableCallback([](void *userdata) {
|
||||
((decltype(this)) userdata)->samples_available();;
|
||||
}, this);
|
||||
|
||||
return true;
|
||||
|
||||
close_fail:
|
||||
snd_pcm_drain(pcm);
|
||||
snd_pcm_close(pcm);
|
||||
pcm = NULL;
|
||||
pcm = nullptr;
|
||||
|
||||
fail:
|
||||
printf("Failed: %s\n", snd_strerror(err));
|
||||
@ -162,7 +151,7 @@ fail:
|
||||
void S9xAlsaSoundDriver::samples_available()
|
||||
{
|
||||
snd_pcm_sframes_t frames_written, frames;
|
||||
int bytes;
|
||||
size_t bytes;
|
||||
|
||||
frames = snd_pcm_avail(pcm);
|
||||
|
||||
@ -206,13 +195,10 @@ void S9xAlsaSoundDriver::samples_available()
|
||||
if (bytes <= 0)
|
||||
return;
|
||||
|
||||
if (sound_buffer_size < bytes || sound_buffer == NULL)
|
||||
{
|
||||
sound_buffer = (uint8 *)realloc(sound_buffer, bytes);
|
||||
sound_buffer_size = bytes;
|
||||
}
|
||||
if (sound_buffer.size() < bytes)
|
||||
sound_buffer.resize(bytes);
|
||||
|
||||
S9xMixSamples(sound_buffer, frames * 2);
|
||||
S9xMixSamples(sound_buffer.data(), frames * 2);
|
||||
|
||||
frames_written = 0;
|
||||
|
||||
@ -221,8 +207,7 @@ void S9xAlsaSoundDriver::samples_available()
|
||||
int result;
|
||||
|
||||
result = snd_pcm_writei(pcm,
|
||||
sound_buffer +
|
||||
snd_pcm_frames_to_bytes(pcm, frames_written),
|
||||
&sound_buffer[snd_pcm_frames_to_bytes(pcm, frames_written)],
|
||||
frames - frames_written);
|
||||
|
||||
if (result < 0)
|
||||
|
@ -24,8 +24,7 @@ class S9xAlsaSoundDriver : public S9xSoundDriver
|
||||
|
||||
private:
|
||||
snd_pcm_t *pcm;
|
||||
int sound_buffer_size;
|
||||
uint8 *sound_buffer;
|
||||
std::vector<uint8_t> sound_buffer;
|
||||
int output_buffer_size;
|
||||
};
|
||||
|
||||
|
@ -13,26 +13,22 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static void pulse_samples_available(void *data)
|
||||
{
|
||||
((S9xPulseSoundDriver *)data)->samples_available();
|
||||
}
|
||||
|
||||
S9xPulseSoundDriver::S9xPulseSoundDriver()
|
||||
{
|
||||
mainloop = NULL;
|
||||
context = NULL;
|
||||
stream = NULL;
|
||||
buffer_size = 0;
|
||||
init();
|
||||
}
|
||||
|
||||
void S9xPulseSoundDriver::init()
|
||||
{
|
||||
mainloop = {};
|
||||
context = {};
|
||||
stream = {};
|
||||
buffer_size = {};
|
||||
}
|
||||
|
||||
void S9xPulseSoundDriver::terminate()
|
||||
{
|
||||
S9xSetSamplesAvailableCallback(NULL, NULL);
|
||||
S9xSetSamplesAvailableCallback(nullptr, nullptr);
|
||||
|
||||
if (mainloop)
|
||||
pa_threaded_mainloop_stop(mainloop);
|
||||
@ -110,15 +106,14 @@ static void stream_state_callback(pa_stream *p, void *userdata)
|
||||
|
||||
bool S9xPulseSoundDriver::open_device()
|
||||
{
|
||||
int err = PA_ERR_UNKNOWN;
|
||||
pa_sample_spec ss;
|
||||
pa_buffer_attr buffer_attr;
|
||||
const pa_buffer_attr *actual_buffer_attr;
|
||||
init();
|
||||
|
||||
pa_sample_spec ss;
|
||||
ss.channels = 2;
|
||||
ss.format = PA_SAMPLE_S16NE;
|
||||
ss.rate = Settings.SoundPlaybackRate;
|
||||
|
||||
pa_buffer_attr buffer_attr;
|
||||
buffer_attr.fragsize = -1;
|
||||
buffer_attr.tlength = pa_usec_to_bytes(gui_config->sound_buffer_size * 1000, &ss);
|
||||
buffer_attr.maxlength = buffer_attr.tlength * 2;
|
||||
@ -130,93 +125,59 @@ bool S9xPulseSoundDriver::open_device()
|
||||
printf(" --> (%dhz, 16-bit Stereo, %dms)...",
|
||||
Settings.SoundPlaybackRate,
|
||||
gui_config->sound_buffer_size);
|
||||
fflush(stdout);
|
||||
|
||||
int err = PA_ERR_UNKNOWN;
|
||||
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");
|
||||
if (!context)
|
||||
goto error1;
|
||||
|
||||
pa_context_set_state_callback(context, context_state_cb, this);
|
||||
if ((err = pa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL)) != 0)
|
||||
goto error2;
|
||||
pa_context_connect(context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
|
||||
|
||||
lock();
|
||||
|
||||
if ((err = pa_threaded_mainloop_start(mainloop)) != 0)
|
||||
goto error2;
|
||||
pa_threaded_mainloop_start(mainloop);
|
||||
wait();
|
||||
|
||||
if ((err = pa_context_get_state(context)) != PA_CONTEXT_READY)
|
||||
{
|
||||
printf("Coundn't create context: State: %d\n", err);
|
||||
goto error2;
|
||||
}
|
||||
return false;
|
||||
|
||||
stream = pa_stream_new(context, "Game", &ss, NULL);
|
||||
|
||||
if (!stream)
|
||||
goto error2;
|
||||
stream = pa_stream_new(context, "Game", &ss, nullptr);
|
||||
|
||||
pa_stream_set_state_callback(stream, stream_state_callback, this);
|
||||
|
||||
if (pa_stream_connect_playback(stream,
|
||||
NULL,
|
||||
nullptr,
|
||||
&buffer_attr,
|
||||
PA_STREAM_ADJUST_LATENCY,
|
||||
NULL,
|
||||
NULL) < 0)
|
||||
goto error3;
|
||||
nullptr,
|
||||
nullptr) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wait();
|
||||
|
||||
if (pa_stream_get_state(stream) != PA_STREAM_READY)
|
||||
{
|
||||
goto error3;
|
||||
}
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
printf("OK\n");
|
||||
|
||||
S9xSetSamplesAvailableCallback(pulse_samples_available, this);
|
||||
S9xSetSamplesAvailableCallback([](void *userdata) {
|
||||
((decltype(this)) userdata)->samples_available();;
|
||||
}, this);
|
||||
|
||||
unlock();
|
||||
|
||||
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()
|
||||
{
|
||||
size_t bytes;
|
||||
int samples;
|
||||
const pa_buffer_attr *buffer_attr;
|
||||
void *output_buffer = NULL;
|
||||
|
||||
lock();
|
||||
bytes = pa_stream_writable_size(stream);
|
||||
buffer_attr = pa_stream_get_buffer_attr(stream);
|
||||
size_t bytes = pa_stream_writable_size(stream);
|
||||
auto buffer_attr = pa_stream_get_buffer_attr(stream);
|
||||
unlock();
|
||||
|
||||
buffer_size = buffer_attr->tlength;
|
||||
@ -226,22 +187,22 @@ void S9xPulseSoundDriver::samples_available()
|
||||
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();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.SoundSync && !Settings.TurboMode && !Settings.Mute)
|
||||
{
|
||||
if ((int)bytes < samples * 2)
|
||||
if (Settings.SoundSync && !Settings.TurboMode && !Settings.Mute)
|
||||
{
|
||||
int usec_to_sleep = ((samples >> 1) - (bytes >> 2)) * 10000 /
|
||||
int usec_to_sleep = (frames_available - frames_writable) * 10000 /
|
||||
(Settings.SoundPlaybackRate / 100);
|
||||
usleep(usec_to_sleep > 0 ? usec_to_sleep : 0);
|
||||
lock();
|
||||
@ -250,16 +211,17 @@ void S9xPulseSoundDriver::samples_available()
|
||||
}
|
||||
}
|
||||
|
||||
bytes = MIN((int)bytes, samples * 2) & ~1;
|
||||
bytes = MIN(bytes, samples * 2) & ~1;
|
||||
|
||||
if (!bytes)
|
||||
return;
|
||||
|
||||
lock();
|
||||
|
||||
void *output_buffer;;
|
||||
if (pa_stream_begin_write(stream, &output_buffer, &bytes) != 0)
|
||||
{
|
||||
pa_stream_flush(stream, NULL, NULL);
|
||||
pa_stream_flush(stream, nullptr, nullptr);
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
@ -270,8 +232,8 @@ void S9xPulseSoundDriver::samples_available()
|
||||
return;
|
||||
}
|
||||
|
||||
S9xMixSamples((uint8 *)output_buffer, bytes >> 1);
|
||||
pa_stream_write(stream, output_buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
|
||||
S9xMixSamples((uint8_t *)output_buffer, bytes >> 1);
|
||||
pa_stream_write(stream, output_buffer, bytes, nullptr, 0, PA_SEEK_RELATIVE);
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
@ -9,16 +9,6 @@
|
||||
#include "apu/apu.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()
|
||||
{
|
||||
int snes_samples_available = S9xGetSampleCount();
|
||||
@ -89,7 +79,10 @@ bool S9xSDLSoundDriver::open_device()
|
||||
audiospec.channels = 2;
|
||||
audiospec.format = AUDIO_S16SYS;
|
||||
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;
|
||||
|
||||
printf("SDL sound driver initializing...\n");
|
||||
@ -106,9 +99,10 @@ bool S9xSDLSoundDriver::open_device()
|
||||
printf("OK\n");
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user