1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 18:30:21 +00:00

Adds a first attempt at audio via SDL.

This commit is contained in:
Thomas Harte 2017-11-05 22:29:25 -05:00
parent 13406fedd8
commit 4b68c372c6

View File

@ -23,7 +23,6 @@
namespace { namespace {
struct CRTMachineDelegate: public CRTMachine::Machine::Delegate { struct CRTMachineDelegate: public CRTMachine::Machine::Delegate {
void machine_did_change_clock_rate(CRTMachine::Machine *machine) { void machine_did_change_clock_rate(CRTMachine::Machine *machine) {
best_effort_updater->set_clock_rate(machine->get_clock_rate()); best_effort_updater->set_clock_rate(machine->get_clock_rate());
} }
@ -35,7 +34,6 @@ struct CRTMachineDelegate: public CRTMachine::Machine::Delegate {
}; };
struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate { struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate {
void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) { void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) {
machine->crt_machine()->run_for(Cycles(cycles)); machine->crt_machine()->run_for(Cycles(cycles));
} }
@ -43,6 +41,20 @@ struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegat
Machine::DynamicMachine *machine; Machine::DynamicMachine *machine;
}; };
// This is set to a relatively large number for now.
const int AudioBufferSize = 1024;
struct SpeakerDelegate: public Outputs::Speaker::Delegate {
void speaker_did_complete_samples(Outputs::Speaker *speaker, const std::vector<int16_t> &buffer) {
if(SDL_GetQueuedAudioSize(audio_device) < AudioBufferSize*3)
SDL_QueueAudio(audio_device, reinterpret_cast<const void *>(buffer.data()), static_cast<Uint32>(buffer.size() * sizeof(uint16_t)));
updater->update();
}
SDL_AudioDeviceID audio_device;
Concurrency::BestEffortUpdater *updater;
};
bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) { bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) {
#define BIND(x, y) case SDL_SCANCODE_##x: key = Inputs::Keyboard::Key::y; break; #define BIND(x, y) case SDL_SCANCODE_##x: key = Inputs::Keyboard::Key::y; break;
switch(scancode) { switch(scancode) {
@ -124,6 +136,7 @@ int main(int argc, char *argv[]) {
Concurrency::BestEffortUpdater updater; Concurrency::BestEffortUpdater updater;
BestEffortUpdaterDelegate best_effort_updater_delegate; BestEffortUpdaterDelegate best_effort_updater_delegate;
CRTMachineDelegate crt_delegate; CRTMachineDelegate crt_delegate;
SpeakerDelegate speaker_delegate;
// Create and configure a machine. // Create and configure a machine.
std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front())); std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front()));
@ -131,6 +144,7 @@ int main(int argc, char *argv[]) {
updater.set_clock_rate(machine->crt_machine()->get_clock_rate()); updater.set_clock_rate(machine->crt_machine()->get_clock_rate());
crt_delegate.best_effort_updater = &updater; crt_delegate.best_effort_updater = &updater;
best_effort_updater_delegate.machine = machine.get(); best_effort_updater_delegate.machine = machine.get();
speaker_delegate.updater = &updater;
machine->crt_machine()->set_delegate(&crt_delegate); machine->crt_machine()->set_delegate(&crt_delegate);
updater.set_delegate(&best_effort_updater_delegate); updater.set_delegate(&best_effort_updater_delegate);
@ -161,13 +175,6 @@ int main(int argc, char *argv[]) {
SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context); SDL_GL_MakeCurrent(window, gl_context);
// Create an audio pipe.
// SDL_AudioSpec desired_audio_spec;
// SDL_AudioSpec obtained_audio_spec;
// desired_audio_spec.freq = 192000; // An arbitrary high number.
// desired_audio_spec.format = AUDIO_S16;
// desired_audio_spec.channels = 1;
// Setup output, assuming a CRT machine for now, and prepare a best-effort updater. // Setup output, assuming a CRT machine for now, and prepare a best-effort updater.
machine->crt_machine()->setup_output(4.0 / 3.0); machine->crt_machine()->setup_output(4.0 / 3.0);
machine->crt_machine()->get_crt()->set_output_gamma(2.2f); machine->crt_machine()->get_crt()->set_output_gamma(2.2f);
@ -202,7 +209,21 @@ int main(int argc, char *argv[]) {
// For now, lie about audio output intentions. // For now, lie about audio output intentions.
auto speaker = machine->crt_machine()->get_speaker(); auto speaker = machine->crt_machine()->get_speaker();
if(speaker) { if(speaker) {
speaker->set_output_rate(44100, 1024); // Create an audio pipe.
SDL_AudioSpec desired_audio_spec;
SDL_AudioSpec obtained_audio_spec;
SDL_zero(desired_audio_spec);
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;
desired_audio_spec.samples = AudioBufferSize;
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_delegate(&speaker_delegate);
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
} }
// Run the main event loop until the OS tells us to quit. // Run the main event loop until the OS tells us to quit.