Add audio subsystem skeleton with a working Linux PCM playback path
Cross-platform audiostream/audio API with per-platform hooks for PSP/Dolphin/Linux. Linux is fully wired end-to-end through SDL2 (device open, volume-mixed queueing, finish detection via SDL_GetQueuedAudioSize) and verified playing a generated test tone in engine.c. PSP and Dolphin hooks are stubbed for now.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "audiostreamlinux.h"
|
||||
#include "audio/audiostream.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
errorret_t audioStreamLinuxInit(audiostream_t *stream) {
|
||||
assertNotNull(stream, "Stream cannot be NULL.");
|
||||
|
||||
SDL_AudioSpec desired;
|
||||
memoryZero(&desired, sizeof(SDL_AudioSpec));
|
||||
desired.freq = (int) stream->pcm.sampleRate;
|
||||
desired.format = AUDIO_S16SYS;
|
||||
desired.channels = stream->pcm.channels;
|
||||
desired.samples = 4096;
|
||||
|
||||
stream->platform.device = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, 0);
|
||||
if(stream->platform.device == 0) {
|
||||
errorThrow("Failed to open SDL2 audio device: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t audioStreamLinuxDispose(audiostream_t *stream) {
|
||||
assertNotNull(stream, "Stream cannot be NULL.");
|
||||
|
||||
SDL_CloseAudioDevice(stream->platform.device);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t audioStreamLinuxBuffer(audiostream_t *stream) {
|
||||
assertNotNull(stream, "Stream cannot be NULL.");
|
||||
|
||||
uint8_t *mixed = memoryAllocate(stream->dataSize);
|
||||
memoryZero(mixed, stream->dataSize);
|
||||
SDL_MixAudioFormat(
|
||||
mixed, stream->data, AUDIO_S16SYS, (Uint32) stream->dataSize,
|
||||
(stream->volume * SDL_MIX_MAXVOLUME) / 0xFF
|
||||
);
|
||||
|
||||
int queued = SDL_QueueAudio(
|
||||
stream->platform.device, mixed, (Uint32) stream->dataSize
|
||||
);
|
||||
memoryFree(mixed);
|
||||
|
||||
if(queued != 0) {
|
||||
errorThrow("Failed to queue SDL2 audio data: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_PauseAudioDevice(stream->platform.device, 0);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
bool_t audioStreamLinuxIsFinished(audiostream_t *stream) {
|
||||
assertNotNull(stream, "Stream cannot be NULL.");
|
||||
|
||||
return SDL_GetQueuedAudioSize(stream->platform.device) == 0;
|
||||
}
|
||||
Reference in New Issue
Block a user