This commit is contained in:
BearOso 2023-06-28 17:58:00 -05:00
parent db97e698b2
commit bafea657e7
12 changed files with 84 additions and 23 deletions

View File

@ -16,7 +16,7 @@ class S9xSoundDriver
virtual ~S9xSoundDriver()
{
}
virtual void write_samples(int16_t *data, int samples) = 0;
virtual bool write_samples(int16_t *data, int samples) = 0;
virtual int space_free() = 0;
virtual std::pair<int, int> buffer_level() = 0;
virtual void init() = 0;

View File

@ -139,7 +139,7 @@ fail:
return false;
}
void S9xAlsaSoundDriver::write_samples(int16_t *data, int samples)
bool S9xAlsaSoundDriver::write_samples(int16_t *data, int samples)
{
snd_pcm_sframes_t frames_written, frames;
size_t bytes;
@ -149,16 +149,20 @@ void S9xAlsaSoundDriver::write_samples(int16_t *data, int samples)
if (frames < 0)
{
frames = snd_pcm_recover(pcm, frames, 1);
return;
return false;
}
bool result = true;
snd_pcm_nonblock(pcm, 0);
if (frames > samples / 2)
{
frames = samples / 2;
result = false;
}
bytes = snd_pcm_frames_to_bytes(pcm, frames);
if (bytes <= 0)
return;
return false;
frames_written = 0;
while (frames_written < frames)
@ -183,6 +187,8 @@ void S9xAlsaSoundDriver::write_samples(int16_t *data, int samples)
frames_written += result;
}
}
return result;
}
int S9xAlsaSoundDriver::space_free()

View File

@ -19,7 +19,7 @@ class S9xAlsaSoundDriver : public S9xSoundDriver
bool open_device(int playback_rate, int buffer_size_ms) override;
void start() override;
void stop() override;
void write_samples(int16_t *data, int samples) override;
bool write_samples(int16_t *data, int samples) override;
int space_free() override;
std::pair<int, int> buffer_level() override;

View File

@ -7,11 +7,17 @@
#include "s9x_sound_driver_cubeb.hpp"
#include <cstdio>
void S9xCubebSoundDriver::write_samples(int16_t *data, int samples)
bool S9xCubebSoundDriver::write_samples(int16_t *data, int samples)
{
bool retval = true;
if (samples > buffer.space_empty())
{
retval = false;
samples = buffer.space_empty();
}
buffer.push(data, samples);
return retval;
}
S9xCubebSoundDriver::S9xCubebSoundDriver()
@ -74,6 +80,7 @@ long S9xCubebSoundDriver::data_callback(cubeb_stream *stream, void const *input_
auto avail = buffer.avail();
if (avail < nframes * 2)
{
printf("Underrun\n");
auto zeroed_samples = nframes * 2 - avail;
memset(output_buffer, 0, zeroed_samples);
buffer.read((int16_t *)output_buffer + zeroed_samples, nframes * 2 - zeroed_samples);
@ -94,13 +101,19 @@ bool S9xCubebSoundDriver::open_device(int playback_rate, int buffer_size)
params.rate = playback_rate;
params.prefs = CUBEB_STREAM_PREF_NONE;
uint32_t suggested_latency = playback_rate * buffer_size / 1000;
uint32_t min_latency;
cubeb_get_min_latency(context, &params, &min_latency);
if (min_latency > suggested_latency)
{
suggested_latency = min_latency;
printf("Using minimum latency: %d\n", min_latency);
}
auto retval = cubeb_stream_init(context, &stream, "Snes9x",
nullptr, nullptr,
nullptr, &params,
min_latency,
suggested_latency,
&::data_callback,
&state_callback,
this);

View File

@ -23,7 +23,7 @@ class S9xCubebSoundDriver : public S9xSoundDriver
void start() override;
void stop() override;
long data_callback(cubeb_stream *stream, void const *input_buffer, void *output_buffer, long nframes);
void write_samples(int16_t *data, int samples) override;
bool write_samples(int16_t *data, int samples) override;
int space_free() override;
std::pair<int, int> buffer_level() override;

View File

@ -184,7 +184,7 @@ std::pair<int, int> S9xPortAudioSoundDriver::buffer_level()
return { Pa_GetStreamWriteAvailable(audio_stream), output_buffer_size };
}
void S9xPortAudioSoundDriver::write_samples(int16_t *data, int samples)
bool S9xPortAudioSoundDriver::write_samples(int16_t *data, int samples)
{
int frames;
@ -199,8 +199,14 @@ void S9xPortAudioSoundDriver::write_samples(int16_t *data, int samples)
frames -= output_buffer_size >> 1;
}
bool retval = true;
if (frames > samples / 2)
{
retval = false;
frames = samples / 2;
}
Pa_WriteStream(audio_stream, data, frames);
return retval;
}

View File

@ -22,7 +22,7 @@ class S9xPortAudioSoundDriver : public S9xSoundDriver
bool open_device(int playback_rate, int buffer_size) override;
void start() override;
void stop() override;
void write_samples(int16_t *data, int samples) override;
bool write_samples(int16_t *data, int samples) override;
int space_free() override;
std::pair<int, int> buffer_level() override;
void samples_available();

View File

@ -7,21 +7,23 @@
#include "s9x_sound_driver_sdl.hpp"
#include "SDL_audio.h"
void S9xSDLSoundDriver::write_samples(int16_t *data, int samples)
bool S9xSDLSoundDriver::write_samples(int16_t *data, int samples)
{
mutex.lock();
bool retval = true;
if (samples > buffer.space_empty())
{
retval = false;
samples = buffer.space_empty();
}
buffer.push(data, samples);
mutex.unlock();
return retval;
}
void S9xSDLSoundDriver::mix(unsigned char *output, int bytes)
{
mutex.lock();
if (buffer.avail() >= bytes >> 1)
buffer.read((int16_t *)output, bytes >> 1);
mutex.unlock();
}
S9xSDLSoundDriver::S9xSDLSoundDriver()
@ -89,16 +91,12 @@ bool S9xSDLSoundDriver::open_device(int playback_rate, int buffer_size)
int S9xSDLSoundDriver::space_free()
{
mutex.lock();
auto space_empty = buffer.space_empty();
mutex.unlock();
return space_empty;
}
std::pair<int, int> S9xSDLSoundDriver::buffer_level()
{
mutex.lock();
std::pair<int, int> level = { buffer.space_empty(), buffer.buffer_size };
mutex.unlock();
return level;
}

View File

@ -28,7 +28,7 @@ class S9xSDLSoundDriver : public S9xSoundDriver
bool open_device(int playback_rate, int buffer_size) override;
void start() override;
void stop() override;
void write_samples(int16_t *data, int samples) override;
bool write_samples(int16_t *data, int samples) override;
int space_free() override;
std::pair<int, int> buffer_level() override;

View File

@ -49,19 +49,51 @@ void EmuApplication::restartAudio()
void EmuApplication::writeSamples(int16_t *data, int samples)
{
static uint64_t total;
static uint64_t ticks;
static std::chrono::steady_clock::time_point then;
if (config->speed_sync_method == EmuConfig::eSoundSync && !core->isAbnormalSpeed())
{
int iterations = 0;
while (sound_driver->space_free() < samples && iterations < 100)
while (sound_driver->space_free() < samples && iterations < 500)
{
iterations++;
std::this_thread::sleep_for(50us);
}
}
sound_driver->write_samples(data, samples);
auto buffer_level = sound_driver->buffer_level();
core->updateSoundBufferLevel(buffer_level.first, buffer_level.second);
if (!sound_driver->write_samples(data, samples))
{
printf("Overrun\n");
core->clearSoundBuffer();
}
char sym = '*';
int percent = (buffer_level.second - buffer_level.first) * 100 / buffer_level.second;
printf("\033[0;0H>");
if (percent < 50)
sym = '_';
for (int i = 0; i < percent; i+=2)
putchar(sym);
for (int i = percent; i <= 100; i+=2)
putchar('-');
total += percent;
ticks++;
auto now = std::chrono::steady_clock::now();
if (now - then >= std::chrono::seconds(1))
{
then = now;
printf(" %lu %%", total / ticks);
total = 0;
ticks = 0;
}
printf("\n");
printf(" 10 20 30 40 50 60 70 80 90 100");
}
void EmuApplication::startGame()

View File

@ -534,6 +534,11 @@ void Snes9xController::SamplesAvailable()
}
}
void Snes9xController::clearSoundBuffer()
{
S9xClearSamples();
}
void S9xMessage(int message_class, int type, const char *message)
{
S9xSetInfoString(message);

View File

@ -35,6 +35,7 @@ class Snes9xController
void softReset();
void setPaused(bool paused);
void setMessage(std::string message);
void clearSoundBuffer();
std::string getStateFolder();
std::string config_folder;
std::string sram_folder;