2018-11-16 00:42:29 +01:00
|
|
|
/*****************************************************************************\
|
|
|
|
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.
|
|
|
|
\*****************************************************************************/
|
|
|
|
|
2023-06-07 23:06:55 +02:00
|
|
|
#include "s9x_sound_driver_sdl.hpp"
|
2022-06-15 02:09:51 +02:00
|
|
|
#include "SDL_audio.h"
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2023-06-29 00:58:00 +02:00
|
|
|
bool S9xSDLSoundDriver::write_samples(int16_t *data, int samples)
|
2019-02-10 02:18:45 +01:00
|
|
|
{
|
2023-06-29 00:58:00 +02:00
|
|
|
bool retval = true;
|
2023-07-03 22:35:11 +02:00
|
|
|
auto empty = buffer.space_empty();
|
|
|
|
if (samples > empty)
|
2023-06-29 00:58:00 +02:00
|
|
|
{
|
|
|
|
retval = false;
|
2023-07-03 22:35:11 +02:00
|
|
|
buffer.dump(buffer.buffer_size / 2 - empty);
|
2023-06-29 00:58:00 +02:00
|
|
|
}
|
2023-06-07 22:34:10 +02:00
|
|
|
buffer.push(data, samples);
|
2023-06-29 00:58:00 +02:00
|
|
|
|
|
|
|
return retval;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2019-02-07 02:41:33 +01:00
|
|
|
void S9xSDLSoundDriver::mix(unsigned char *output, int bytes)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2019-05-14 22:34:25 +02:00
|
|
|
if (buffer.avail() >= bytes >> 1)
|
|
|
|
buffer.read((int16_t *)output, bytes >> 1);
|
2023-07-03 22:35:11 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
buffer.read((int16_t *)output, buffer.avail());
|
|
|
|
buffer.add_silence(buffer.buffer_size / 2);
|
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2019-02-07 02:41:33 +01:00
|
|
|
S9xSDLSoundDriver::S9xSDLSoundDriver()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-03-23 22:53:43 +01:00
|
|
|
S9xSDLSoundDriver::~S9xSDLSoundDriver()
|
|
|
|
{
|
|
|
|
deinit();
|
|
|
|
}
|
|
|
|
|
2019-02-07 02:41:33 +01:00
|
|
|
void S9xSDLSoundDriver::init()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2019-02-07 02:41:33 +01:00
|
|
|
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
|
|
|
stop();
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2023-06-07 22:34:10 +02:00
|
|
|
void S9xSDLSoundDriver::deinit()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2019-02-07 02:41:33 +01:00
|
|
|
stop();
|
2019-05-14 22:34:25 +02:00
|
|
|
SDL_CloseAudio();
|
2019-02-07 02:41:33 +01:00
|
|
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2019-02-07 02:41:33 +01:00
|
|
|
void S9xSDLSoundDriver::start()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2023-06-07 22:34:10 +02:00
|
|
|
SDL_PauseAudio(0);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2019-02-07 02:41:33 +01:00
|
|
|
void S9xSDLSoundDriver::stop()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2019-05-14 22:34:25 +02:00
|
|
|
SDL_PauseAudio(1);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2023-06-07 22:34:10 +02:00
|
|
|
bool S9xSDLSoundDriver::open_device(int playback_rate, int buffer_size)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2019-05-14 22:34:25 +02:00
|
|
|
audiospec = {};
|
2023-06-07 22:34:10 +02:00
|
|
|
audiospec.freq = playback_rate;
|
2019-05-14 22:34:25 +02:00
|
|
|
audiospec.channels = 2;
|
|
|
|
audiospec.format = AUDIO_S16SYS;
|
2023-06-30 00:44:13 +02:00
|
|
|
audiospec.samples = audiospec.freq * buffer_size / 8 / 1000; // 1/8th buffer per callback
|
2022-03-12 18:19:39 +01:00
|
|
|
audiospec.callback = [](void *userdata, uint8_t *stream, int len) {
|
|
|
|
((S9xSDLSoundDriver *)userdata)->mix((unsigned char *)stream, len);
|
|
|
|
};
|
|
|
|
|
2019-05-14 22:34:25 +02:00
|
|
|
audiospec.userdata = this;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2019-02-07 02:41:33 +01:00
|
|
|
printf("SDL sound driver initializing...\n");
|
|
|
|
printf(" --> (Frequency: %dhz, Latency: %dms)...",
|
2019-05-14 22:34:25 +02:00
|
|
|
audiospec.freq,
|
|
|
|
(audiospec.samples * 1000 / audiospec.freq));
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2019-05-14 22:34:25 +02:00
|
|
|
if (SDL_OpenAudio(&audiospec, NULL) < 0)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2019-02-07 02:41:33 +01:00
|
|
|
printf("Failed\n");
|
2018-12-28 23:32:32 +01:00
|
|
|
return false;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
2019-02-07 02:41:33 +01:00
|
|
|
printf("OK\n");
|
2023-06-30 00:44:13 +02:00
|
|
|
if (buffer_size < 32)
|
|
|
|
buffer_size = 32;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2023-06-30 00:44:13 +02:00
|
|
|
buffer.resize(buffer_size * 4 * audiospec.freq / 1000);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-12-28 23:32:32 +01:00
|
|
|
return true;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
2023-06-07 22:34:10 +02:00
|
|
|
|
|
|
|
int S9xSDLSoundDriver::space_free()
|
|
|
|
{
|
|
|
|
auto space_empty = buffer.space_empty();
|
|
|
|
return space_empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<int, int> S9xSDLSoundDriver::buffer_level()
|
|
|
|
{
|
|
|
|
std::pair<int, int> level = { buffer.space_empty(), buffer.buffer_size };
|
|
|
|
return level;
|
|
|
|
}
|