1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-06 13:31:55 +00:00

Ensures the stereo audio queue is the same length (in time) as the mono.

This commit is contained in:
Thomas Harte 2020-02-16 12:46:25 -05:00
parent d55d077a95
commit ea1c8a3b81

View File

@ -168,10 +168,12 @@ struct MachineRunner {
struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate {
// This is empirically the best that I can seem to do with SDL's timer precision.
static constexpr int buffer_size = 1024;
static constexpr int buffered_samples = 1024;
bool is_stereo = false;
void speaker_did_complete_samples(Outputs::Speaker::Speaker *speaker, const std::vector<int16_t> &buffer) final {
std::lock_guard<std::mutex> lock_guard(audio_buffer_mutex_);
const auto buffer_size = buffered_samples * (is_stereo ? 2 : 1);
if(audio_buffer_.size() > buffer_size) {
audio_buffer_.erase(audio_buffer_.begin(), audio_buffer_.end() - buffer_size);
}
@ -181,9 +183,10 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate {
void audio_callback(Uint8 *stream, int len) {
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));
// SDL buffer length is in bytes, so there's no need to adjust for stereo/mono in here.
const std::size_t sample_length = static_cast<std::size_t>(len) / sizeof(int16_t);
const std::size_t copy_length = std::min(sample_length, audio_buffer_.size());
int16_t *const 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) {
@ -661,13 +664,14 @@ 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.format = AUDIO_S16;
desired_audio_spec.channels = 1 + int(speaker->get_is_stereo());
desired_audio_spec.samples = SpeakerDelegate::buffer_size;
desired_audio_spec.samples = SpeakerDelegate::buffered_samples;
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->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, speaker->get_is_stereo());
speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, obtained_audio_spec.channels == 2);
speaker_delegate.is_stereo = obtained_audio_spec.channels == 2;
speaker->set_delegate(&speaker_delegate);
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
}