Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
9966de77fThis file is pinned to the selected release. Download the original to open it in your design tool.
#include <algorithm>
#include <iostream>
#include "audio.hpp"
#include "simulator.hpp"
#include "window.hpp"
Audio::Audio(std::filesystem::path save_path) {
SDL_AudioSpec want;
SDL_memset(&want, 0, sizeof(want));
want.freq = Simulator::audioSampleHz();
want.format = AUDIO_S16SYS;
want.channels = 2;
// 256 is ~0.5 a frame of samples
want.samples = 256;
want.callback = nullptr;
SDL_AudioSpec have;
device = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
if (device == 0) {
std::cout << "Failed to open audio device: " << SDL_GetError() << "\n";
return;
}
// Unpause audio device.
SDL_PauseAudioDevice(device, 0);
if (!save_path.empty()) {
this->output = std::ofstream(save_path, std::ios::binary | std::ios::trunc);
std::cout << "Saving audio output to " << save_path << "\n";
std::cout << "Convert to WAV file with:\n";
std::cout << "ffmpeg -f s16le -ar " << Simulator::audioSampleHz() << " -ac 2 -i " << save_path << " out.wav\n";
}
}
// Each sample is a sample 16-bit (left, right) pair (4 bytes total per sample).
void Audio::push(int16_t* data, uint32_t length) {
uint32_t samples_queued = SDL_GetQueuedAudioSize(device) / 4;
// Target maximum of 2 frames of samples in the buffer.
uint32_t samples_max = 2 * Simulator::audioSampleHz() / 60;
if (samples_queued < samples_max) {
uint32_t samples = std::min(length / 2, samples_max - samples_queued);
SDL_QueueAudio(device, data, samples * 4);
}
if (output.is_open()) {
output.write(reinterpret_cast<const char*>(data), length * 2);
}
}
Audio::~Audio() {
SDL_CloseAudioDevice(device);
}