mirror of https://github.com/snes9xgit/snes9x.git
Working.
This commit is contained in:
parent
db97e698b2
commit
bafea657e7
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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, ¶ms, &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, ¶ms,
|
||||
min_latency,
|
||||
suggested_latency,
|
||||
&::data_callback,
|
||||
&state_callback,
|
||||
this);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -534,6 +534,11 @@ void Snes9xController::SamplesAvailable()
|
|||
}
|
||||
}
|
||||
|
||||
void Snes9xController::clearSoundBuffer()
|
||||
{
|
||||
S9xClearSamples();
|
||||
}
|
||||
|
||||
void S9xMessage(int message_class, int type, const char *message)
|
||||
{
|
||||
S9xSetInfoString(message);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue