Gtk: Clean up a couple sound drivers.

Make them more idiomatic C++.
This commit is contained in:
BearOso 2022-03-12 11:19:39 -06:00
parent 0a94eaa6dc
commit a8fafcd94c
4 changed files with 74 additions and 134 deletions

View File

@ -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)

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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;
}