Drive gameplay with audio instead of timer

This commit is contained in:
Simon Gellis 2024-10-23 22:50:44 -04:00
parent 3d2c6cbddf
commit a479d3c0b3
4 changed files with 40 additions and 27 deletions

41
audio.c
View File

@ -1,14 +1,30 @@
#include <audio.h>
#include <stdio.h>
void audioCallback(void *userdata, uint8_t *stream, int len) {
AudioContext *aud;
SDL_assert(len == 834 * 4);
aud = userdata;
if (!aud->filled) {
/* too little data, play silence */
SDL_memset4(stream, 0, 834);
return;
}
SDL_memcpy4(stream, aud->buffers[aud->current], 834);
++aud->current;
aud->current %= 2;
aud->filled -= 1;
}
int audioInit(AudioContext *aud) {
SDL_AudioSpec spec;
spec.freq = 41700;
spec.format = AUDIO_S16;
spec.channels = 2;
spec.samples = 1024;
spec.callback = NULL;
spec.userdata = NULL;
spec.samples = 834;
spec.callback = &audioCallback;
spec.userdata = aud;
aud->id = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
aud->paused = true;
@ -16,21 +32,34 @@ int audioInit(AudioContext *aud) {
fprintf(stderr, "could not open audio device: %s\n", SDL_GetError());
return -1;
}
aud->current = 0;
aud->filled = 0;
return 0;
}
int audioUpdate(AudioContext *aud, void *data, uint32_t bytes) {
int filled;
if (!aud->id) return -1;
SDL_assert(bytes == 834 * 4);
if (SDL_QueueAudio(aud->id, data, bytes)) {
fprintf(stderr, "could not write audio: %s\n", SDL_GetError());
return -1;
SDL_LockAudioDevice(aud->id);
if (aud->filled < 2) {
int next = (aud->current + aud->filled) % 2;
SDL_memcpy4(aud->buffers[next], data, bytes / 4);
aud->filled += 1;
}
filled = aud->filled;
SDL_UnlockAudioDevice(aud->id);
if (aud->paused) {
SDL_PauseAudioDevice(aud->id, false);
aud->paused = false;
}
while (filled > 1) {
SDL_Delay(0);
filled = aud->filled;
}
return 0;
}

View File

@ -7,6 +7,9 @@
typedef struct {
SDL_AudioDeviceID id;
bool paused;
uint32_t buffers[2][834];
int current;
int filled;
} AudioContext;
int audioInit(AudioContext *aud);

17
game.c
View File

@ -6,19 +6,6 @@
#include <stdbool.h>
#include <time.h>
int sleepNanos(long int ns) {
struct timespec time;
if (ns < 0) return 0;
time.tv_sec = ns / 1000000000;
time.tv_nsec = ns % 1000000000;
return nanosleep(&time, NULL);
}
long int tickNs() {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return (time.tv_sec * 1000000000) + time.tv_nsec;
}
typedef struct {
GraphicsContext *gfx;
AudioContext aud;
@ -52,7 +39,6 @@ int runGame(VB *sim, GraphicsContext *gfx) {
SDL_Event event;
GameState state;
ControllerState ctrl;
uint64_t ticks, prevTicks;
state.gfx = gfx;
audioInit(&state.aud);
@ -67,10 +53,7 @@ int runGame(VB *sim, GraphicsContext *gfx) {
while (1) {
clocks = MAX_STEP_CLOCKS;
prevTicks = tickNs();
vbEmulate(sim, &clocks);
ticks = tickNs();
sleepNanos(((MAX_STEP_CLOCKS - clocks) * 50) - (ticks - prevTicks));
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {

View File

@ -28,17 +28,15 @@ output/%.o: %.c
@mkdir -p output
@$(CC) -c -o $@ $< -I . \
-I shrooms-vb-core/core $(SDL2FLAGS) \
-D _POSIX_C_SOURCE=199309L \
-O3 -flto -fno-strict-aliasing \
-Werror -std=c11 -Wall -Wextra -Wpedantic
-Werror -std=c90 -Wall -Wextra -Wpedantic
output/vb.o: shrooms-vb-core/core/vb.c
@mkdir -p output
@$(CC) -c -o $@ $< -I . \
-I shrooms-vb-core/core $(SDL2FLAGS) \
-D _POSIX_C_SOURCE=199309L \
-O3 -flto -fno-strict-aliasing \
-Werror -std=c11 -Wall -Wextra -Wpedantic
-Werror -std=c90 -Wall -Wextra -Wpedantic
output/%.o: assets/%.bin
@mkdir -p output