snes9x/gtk/src/gtk_sound_driver_sdl.cpp

135 lines
3.1 KiB
C++
Raw Normal View History

/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
2010-09-25 17:46:12 +02:00
#include "gtk_sound_driver_sdl.h"
#include "gtk_s9x.h"
2010-09-25 17:46:12 +02:00
static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
2010-09-25 17:46:12 +02:00
{
((S9xSDLSoundDriver *)userdata)->mix((unsigned char *)stream, len);
2010-09-25 17:46:12 +02:00
}
2019-02-10 02:18:45 +01:00
static void c_samples_available(void *data)
2010-09-25 17:46:12 +02:00
{
2019-02-10 02:18:45 +01:00
((S9xSDLSoundDriver *)data)->samples_available();
}
void S9xSDLSoundDriver::samples_available()
{
int snes_samples_available = S9xGetSampleCount();
S9xMixSamples((uint8 *)temp, snes_samples_available);
if (Settings.SoundSync && !Settings.TurboMode && !Settings.Mute)
{
mutex.lock();
int samples = buffer->space_empty();
mutex.unlock();
while (samples < snes_samples_available)
{
usleep(100);
mutex.lock();
samples = buffer->space_empty();
mutex.unlock();
}
}
mutex.lock();
buffer->push(temp, snes_samples_available);
mutex.unlock();
2010-09-25 17:46:12 +02:00
}
void S9xSDLSoundDriver::mix(unsigned char *output, int bytes)
2010-09-25 17:46:12 +02:00
{
2019-02-10 02:18:45 +01:00
mutex.lock();
if (buffer->avail() >= bytes >> 1)
buffer->read((int16_t *)output, bytes >> 1);
mutex.unlock();
2010-09-25 17:46:12 +02:00
}
S9xSDLSoundDriver::S9xSDLSoundDriver()
2010-09-25 17:46:12 +02:00
{
2019-02-10 02:18:45 +01:00
buffer = NULL;
2010-09-25 17:46:12 +02:00
audiospec = NULL;
}
void S9xSDLSoundDriver::init()
2010-09-25 17:46:12 +02:00
{
SDL_InitSubSystem(SDL_INIT_AUDIO);
stop();
2010-09-25 17:46:12 +02:00
}
void S9xSDLSoundDriver::terminate()
2010-09-25 17:46:12 +02:00
{
stop();
2010-09-25 17:46:12 +02:00
if (audiospec)
{
SDL_CloseAudio();
2019-02-10 02:18:45 +01:00
if (buffer)
delete buffer;
free(audiospec);
2010-09-25 17:46:12 +02:00
audiospec = NULL;
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
2010-09-25 17:46:12 +02:00
}
void S9xSDLSoundDriver::start()
2010-09-25 17:46:12 +02:00
{
if (!gui_config->mute_sound)
{
if (audiospec)
{
SDL_PauseAudio(0);
2010-09-25 17:46:12 +02:00
}
}
}
void S9xSDLSoundDriver::stop()
2010-09-25 17:46:12 +02:00
{
if (audiospec)
{
SDL_PauseAudio(1);
2010-09-25 17:46:12 +02:00
}
}
bool S9xSDLSoundDriver::open_device()
2010-09-25 17:46:12 +02:00
{
audiospec = (SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
2010-09-25 17:46:12 +02:00
audiospec->freq = Settings.SoundPlaybackRate;
audiospec->channels = 2;
audiospec->format = AUDIO_S16SYS;
2019-02-10 02:18:45 +01:00
audiospec->samples = (gui_config->sound_buffer_size * audiospec->freq / 1000) >> 2;
2010-09-25 17:46:12 +02:00
audiospec->callback = sdl_audio_callback;
audiospec->userdata = this;
printf("SDL sound driver initializing...\n");
printf(" --> (Frequency: %dhz, Latency: %dms)...",
audiospec->freq,
2019-02-10 02:18:45 +01:00
(audiospec->samples * 1000 / audiospec->freq));
2010-09-25 17:46:12 +02:00
if (SDL_OpenAudio(audiospec, NULL) < 0)
2010-09-25 17:46:12 +02:00
{
printf("Failed\n");
2010-09-25 17:46:12 +02:00
free(audiospec);
2010-09-25 17:46:12 +02:00
audiospec = NULL;
return false;
2010-09-25 17:46:12 +02:00
}
printf("OK\n");
2010-09-25 17:46:12 +02:00
2019-02-10 02:18:45 +01:00
buffer = new Resampler(gui_config->sound_buffer_size * audiospec->freq / 500);
buffer->time_ratio(1.0);
S9xSetSamplesAvailableCallback(c_samples_available, this);
2010-09-25 17:46:12 +02:00
return true;
2010-09-25 17:46:12 +02:00
}