joeylib2/examples/audio/audio.c

120 lines
3.2 KiB
C

// Audio demo: starts an embedded .MOD on entry, triggers a short
// digital SFX every time SPACE is tapped, and exits on ESC. The MOD
// and SFX bytes live in test_assets.h, generated from assets/test.mod
// and assets/test.sfx by the audio-asset build pipeline.
//
// On platforms where the audio HAL is still a stub (DOS / ST / IIgs
// at the moment), joeyAudioInit returns false, every audio call is a
// quiet no-op, and the demo runs as a silent input loop -- you can
// confirm the build links and the input plumbing still works without
// hearing anything.
#include <stdio.h>
#include <joey/joey.h>
#include "test_assets.h"
#define SFX_SLOT 0
#define SFX_RATE_HZ 8000
#define COLOR_BG 0
#define COLOR_HINT 1
#define COLOR_BAR 2
#define BAR_X 16
#define BAR_Y 88
#define BAR_W (SURFACE_WIDTH - 32)
#define BAR_H 16
static void buildPalette(SurfaceT *screen) {
uint16_t colors[SURFACE_COLORS_PER_PALETTE];
uint16_t i;
for (i = 0; i < SURFACE_COLORS_PER_PALETTE; i++) {
colors[i] = 0x0000;
}
colors[COLOR_BG] = 0x0000;
colors[COLOR_HINT] = 0x0444;
colors[COLOR_BAR] = 0x00F0;
paletteSet(screen, 0, colors);
}
// Visual feedback for "audio is running, but you cannot tell on a
// stub HAL": pulse a horizontal bar between the hint color and the
// active color whenever SFX has fired this frame.
static void initialPaint(SurfaceT *screen, bool audioOk) {
surfaceClear(screen, COLOR_BG);
fillRect(screen, BAR_X, BAR_Y, BAR_W, BAR_H,
audioOk ? COLOR_HINT : COLOR_BG);
surfacePresent(screen);
}
int main(void) {
JoeyConfigT config;
SurfaceT *screen;
bool audioOk;
int16_t flashFrames;
config.hostMode = HOST_MODE_TAKEOVER;
config.codegenBytes = 8 * 1024;
config.maxSurfaces = 4;
config.audioBytes = 64 * 1024;
config.assetBytes = 128 * 1024;
if (!joeyInit(&config)) {
fprintf(stderr, "joeyInit failed: %s\n", joeyLastError());
return 1;
}
screen = surfaceGetScreen();
if (screen == NULL) {
fprintf(stderr, "surfaceGetScreen returned NULL\n");
joeyShutdown();
return 1;
}
audioOk = joeyAudioInit();
if (audioOk) {
joeyAudioPlayMod(gTestMod, gTestMod_len, true);
}
buildPalette(screen);
scbSetRange(screen, 0, SURFACE_HEIGHT - 1, 0);
initialPaint(screen, audioOk);
flashFrames = 0;
for (;;) {
joeyWaitVBL();
joeyInputPoll();
joeyAudioFrameTick();
if (joeyKeyPressed(KEY_ESCAPE)) {
break;
}
if (joeyKeyPressed(KEY_SPACE)) {
joeyAudioPlaySfx(SFX_SLOT, gTestSfx, gTestSfx_len, SFX_RATE_HZ);
flashFrames = 8;
}
if (flashFrames > 0) {
fillRect(screen, BAR_X, BAR_Y, BAR_W, BAR_H, COLOR_BAR);
surfacePresentRect(screen, BAR_X, BAR_Y, BAR_W, BAR_H);
flashFrames--;
if (flashFrames == 0) {
fillRect(screen, BAR_X, BAR_Y, BAR_W, BAR_H, COLOR_HINT);
surfacePresentRect(screen, BAR_X, BAR_Y, BAR_W, BAR_H);
}
}
}
if (audioOk) {
joeyAudioStopMod();
joeyAudioShutdown();
}
joeyShutdown();
return 0;
}