1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Switches to using the supply-on-demand audio route through SDL.

This gives an additional hook from which machine updates can be hooked, so separates that buffer size from any implicit frame rate assumptions.
This commit is contained in:
Thomas Harte 2017-11-22 19:36:39 -05:00
parent dc4f58e40c
commit c1b7bceec8

View File

@ -42,17 +42,41 @@ struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegat
}; };
// This is set to a relatively large number for now. // This is set to a relatively large number for now.
const int AudioBufferSize = 1024;
struct SpeakerDelegate: public Outputs::Speaker::Delegate { struct SpeakerDelegate: public Outputs::Speaker::Delegate {
static const int buffer_size = 1024;
void speaker_did_complete_samples(Outputs::Speaker *speaker, const std::vector<int16_t> &buffer) { void speaker_did_complete_samples(Outputs::Speaker *speaker, const std::vector<int16_t> &buffer) {
if(SDL_GetQueuedAudioSize(audio_device) < AudioBufferSize*3) std::lock_guard<std::mutex> lock_guard(audio_buffer_mutex_);
SDL_QueueAudio(audio_device, reinterpret_cast<const void *>(buffer.data()), static_cast<Uint32>(buffer.size() * sizeof(uint16_t))); if(audio_buffer_.size() > buffer_size) {
audio_buffer_.erase(audio_buffer_.begin(), audio_buffer_.end() - buffer_size);
}
audio_buffer_.insert(audio_buffer_.end(), buffer.begin(), buffer.end());
}
void audio_callback(Uint8 *stream, int len) {
updater->update(); updater->update();
std::lock_guard<std::mutex> lock_guard(audio_buffer_mutex_);
std::size_t sample_length = static_cast<std::size_t>(len) / sizeof(int16_t);
std::size_t copy_length = std::min(sample_length, audio_buffer_.size());
int16_t *target = static_cast<int16_t *>(static_cast<void *>(stream));
std::memcpy(stream, audio_buffer_.data(), copy_length * sizeof(int16_t));
if(copy_length < sample_length) {
std::memset(&target[copy_length], 0, (sample_length - copy_length) * sizeof(int16_t));
}
audio_buffer_.erase(audio_buffer_.begin(), audio_buffer_.begin() + copy_length);
}
static void SDL_audio_callback(void *userdata, Uint8 *stream, int len) {
reinterpret_cast<SpeakerDelegate *>(userdata)->audio_callback(stream, len);
} }
SDL_AudioDeviceID audio_device; SDL_AudioDeviceID audio_device;
Concurrency::BestEffortUpdater *updater; Concurrency::BestEffortUpdater *updater;
std::mutex audio_buffer_mutex_;
std::vector<int16_t> audio_buffer_;
}; };
bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) { bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) {
@ -345,11 +369,13 @@ int main(int argc, char *argv[]) {
desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine? desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine?
desired_audio_spec.format = AUDIO_S16; desired_audio_spec.format = AUDIO_S16;
desired_audio_spec.channels = 1; desired_audio_spec.channels = 1;
desired_audio_spec.samples = AudioBufferSize; desired_audio_spec.samples = SpeakerDelegate::buffer_size;
desired_audio_spec.callback = SpeakerDelegate::SDL_audio_callback;
desired_audio_spec.userdata = &speaker_delegate;
speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
speaker->set_output_rate(obtained_audio_spec.freq, obtained_audio_spec.samples); speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples);
speaker->set_delegate(&speaker_delegate); speaker->set_delegate(&speaker_delegate);
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0); SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
} }