18 unsigned wantedFreq,
unsigned wantedSamples)
22 SDL_AudioSpec desired;
23 desired.freq = wantedFreq;
24 desired.samples = std::bit_ceil(wantedSamples);
26 desired.format = AUDIO_F32SYS;
27 desired.callback = audioCallbackHelper;
28 desired.userdata =
this;
30 SDL_AudioSpec obtained;
31 deviceID = SDL_OpenAudioDevice(
nullptr, SDL_FALSE, &desired, &obtained,
32 SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
34 throw MSXException(
"Unable to open SDL audio: ", SDL_GetError());
37 frequency = obtained.freq;
38 fragmentSize = obtained.samples;
40 mixBufferSize = 3 * (obtained.size /
sizeof(float)) + 2;
41 mixBuffer.
resize(mixBufferSize);
47 SDL_CloseAudioDevice(deviceID);
50 void SDLSoundDriver::reInit()
52 SDL_LockAudioDevice(deviceID);
55 SDL_UnlockAudioDevice(deviceID);
62 SDL_PauseAudioDevice(deviceID, 1);
71 SDL_PauseAudioDevice(deviceID, 0);
85 void SDLSoundDriver::audioCallbackHelper(
void* userdata, uint8_t* strm,
int len)
87 assert((len & 7) == 0);
89 audioCallback(
reinterpret_cast<float*
>(strm), len /
sizeof(float));
92 unsigned SDLSoundDriver::getBufferFilled()
const
94 int result = writeIdx - readIdx;
95 if (result < 0) result += mixBufferSize;
96 assert((0 <= result) && (
unsigned(result) < mixBufferSize));
100 unsigned SDLSoundDriver::getBufferFree()
const
106 int result = mixBufferSize - 2 - getBufferFilled();
107 assert((0 <= result) && (
unsigned(result) < mixBufferSize));
111 void SDLSoundDriver::audioCallback(
float* stream,
unsigned len)
113 assert((len & 1) == 0);
114 unsigned available = getBufferFilled();
115 unsigned num =
std::min(len, available);
116 if ((readIdx + num) < mixBufferSize) {
117 memcpy(stream, &mixBuffer[readIdx], num *
sizeof(
float));
120 unsigned len1 = mixBufferSize - readIdx;
121 memcpy(stream, &mixBuffer[readIdx], len1 *
sizeof(
float));
122 unsigned len2 = num - len1;
123 memcpy(&stream[len1], &mixBuffer[0], len2 *
sizeof(
float));
126 int missing = len - available;
129 memset(&stream[available], 0, missing *
sizeof(
float));
135 SDL_LockAudioDevice(deviceID);
137 unsigned free = getBufferFree();
140 if (board && !board->getMSXMixer().isSynchronousMode() &&
143 SDL_UnlockAudioDevice(deviceID);
145 SDL_LockAudioDevice(deviceID);
146 board->getRealTime().resync();
147 free = getBufferFree();
148 }
while (len > free);
155 if ((writeIdx + len) < mixBufferSize) {
156 memcpy(&mixBuffer[writeIdx], buffer, len *
sizeof(
float));
159 unsigned len1 = mixBufferSize - writeIdx;
160 memcpy(&mixBuffer[writeIdx], buffer, len1 *
sizeof(
float));
161 unsigned len2 = len - len1;
162 memcpy(&mixBuffer[0], &buffer[len1], len2 *
sizeof(
float));
166 SDL_UnlockAudioDevice(deviceID);
ThrottleManager & getThrottleManager()
void resize(size_t size)
Grow or shrink the memory block.
Contains the main loop of openMSX.
MSXMotherBoard * getMotherBoard() const
GlobalSettings & getGlobalSettings()
void unmute() override
Unmute the sound system.
void mute() override
Mute the sound system.
~SDLSoundDriver() override
unsigned getFrequency() const override
Returns the actual sample frequency.
SDLSoundDriver(const SDLSoundDriver &)=delete
void uploadBuffer(float *buffer, unsigned len) override
unsigned getSamples() const override
Get the number of samples that should be created 'per fragment'.
bool isThrottled() const
Ask if throttling is enabled.
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
void sleep(uint64_t us)
Sleep for the specified amount of time (in us).
This file implemented 3 utility functions: