From 8ff967a0bcc05c0f07cde9d19758389cd4a7402b Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Sat, 16 Nov 2024 14:19:00 +0300 Subject: [PATCH] Wii: preload some audio voices --- ball/main.c | 19 +++++++ share/audio.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++- share/audio.h | 1 + 3 files changed, 171 insertions(+), 1 deletion(-) diff --git a/ball/main.c b/ball/main.c index cf123be51..c3e14ce6d 100644 --- a/ball/main.c +++ b/ball/main.c @@ -45,6 +45,7 @@ #include "package.h" #include "log.h" #include "game_client.h" +#include "game_common.h" #include "strbuf/substr.h" #include "strbuf/joinstr.h" #include "lang.h" @@ -942,6 +943,24 @@ static int main_init(int argc, char *argv[]) /* Initialize audio. */ audio_init(); + audio_cache(AUD_MENU); + audio_cache(AUD_BALL); + audio_cache(AUD_BUMPS); + audio_cache(AUD_BUMPM); + audio_cache(AUD_BUMPL); + audio_cache(AUD_COIN); + audio_cache(AUD_TICK); + audio_cache(AUD_TOCK); + audio_cache(AUD_SWITCH); + audio_cache(AUD_JUMP); + audio_cache(AUD_GOAL); + audio_cache(AUD_SCORE); + audio_cache(AUD_FALL); + audio_cache(AUD_TIME); + audio_cache(AUD_OVER); + audio_cache(AUD_GROW); + audio_cache(AUD_SHRINK); + audio_cache(AUD_JUMP); tilt_init(); /* Initialize video. */ diff --git a/share/audio.c b/share/audio.c index 8b11a16dd..88eddd017 100644 --- a/share/audio.c +++ b/share/audio.c @@ -33,8 +33,19 @@ #define AUDIO_RATE 44100 #define AUDIO_CHAN 2 +struct cached_voice +{ + char *name; + short *samples; + int num_samples; /* sample = 16 bits of data, one channel only */ + int chan; + struct cached_voice *next; +}; + struct voice { + struct cached_voice *cached_voice; + int cached_voice_start; OggVorbis_File vf; float amp; float damp; @@ -55,6 +66,7 @@ static struct voice *music = NULL; static struct voice *queue = NULL; static struct voice *voices = NULL; static short *buffer = NULL; +static struct cached_voice *cached_voices = NULL; static ov_callbacks callbacks = { fs_ov_read, fs_ov_seek, fs_ov_close, fs_ov_tell @@ -71,6 +83,113 @@ static ov_callbacks callbacks = { else (d) = (short) T; \ } +static int cached_voice_step(struct voice *V, float volume, Uint8 *stream, int length) +{ + short *obuf = (short *) stream; + + const struct cached_voice *CV = V->cached_voice; + int i, n = 1, c = 0, r = 0; + + /* Compute the total request size for the current stream. */ + int sample_size = length / sizeof(short); + + if (V->chan == 1) r = sample_size / 2; + if (V->chan == 2) r = sample_size ; + + /* While data is coming in and data is still needed... */ + + if (r == 0) return 1; + + n = r; + if (n > CV->num_samples - V->cached_voice_start) { + n = CV->num_samples - V->cached_voice_start; + } + /* Mix mono audio. */ + + short *ibuf = CV->samples + V->cached_voice_start; + if (V->chan == 1) + for (i = 0; i < n; i += 1) + { + short M = (short) (V->amp * volume * ibuf[i]); + + MIX(obuf[c], M); c++; + MIX(obuf[c], M); c++; + + V->amp += V->damp; + + if (V->amp < 0.0f) V->amp = 0.0; + if (V->amp > 1.0f) V->amp = 1.0; + } + + /* Mix stereo audio. */ + + if (V->chan == 2) + for (i = 0; i < n; i += 2) + { + short L = (short) (V->amp * volume * ibuf[i + 0]); + short R = (short) (V->amp * volume * ibuf[i + 1]); + + MIX(obuf[c], L); c++; + MIX(obuf[c], R); c++; + + V->amp += V->damp; + + if (V->amp < 0.0f) V->amp = 0.0; + if (V->amp > 1.0f) V->amp = 1.0; + } + + V->cached_voice_start += n; + return n < r; +} + +static struct cached_voice *cached_voice_init(const char *filename) +{ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + int order = 1; +#else + int order = 0; +#endif + struct cached_voice *CV; + fs_file fp; + + /* Allocate and initialize a new voice structure. */ + + if ((CV = (struct cached_voice *) calloc(1, sizeof (struct cached_voice)))) + { + /* Note the name. */ + + CV->name = strdup(filename); + + /* Attempt to open the named Ogg stream. */ + + if ((fp = fs_open_read(filename))) + { + OggVorbis_File vf; + if (ov_open_callbacks(fp, &vf, NULL, 0, callbacks) == 0) + { + vorbis_info *info = ov_info(&vf, -1); + CV->chan = info->channels; + + ov_raw_seek(&vf, 0); // Workaround for https://stackoverflow.com/questions/8653670 + CV->num_samples = ov_pcm_total(&vf, 0) * CV->chan; + int bufsize = CV->num_samples * sizeof(short); + CV->samples = malloc(bufsize); + + long read = 0; + char *buffer = (char *)CV->samples; + while (read < bufsize) { + int b = 0; + read += ov_read(&vf, buffer + read, bufsize - read, + order, 2, 1, &b); + } + + ov_clear(&vf); + } else fs_close(fp); + } + } + return CV; +} + static int voice_step(struct voice *V, float volume, Uint8 *stream, int length) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -79,6 +198,8 @@ static int voice_step(struct voice *V, float volume, Uint8 *stream, int length) int order = 0; #endif + if (V->cached_voice) return cached_voice_step(V, volume, stream, length); + short *obuf = (short *) stream; char *ibuf = (char *) buffer; @@ -160,6 +281,22 @@ static struct voice *voice_init(const char *filename, float a) V->name = strdup(filename); + struct cached_voice *CV = NULL; + for (CV = cached_voices; CV; CV = CV->next) + if (strcmp(CV->name, filename) == 0) { + V->cached_voice = CV; + V->cached_voice_start = 0; + V->amp = a; + V->damp = 0; + V->chan = CV->chan; + V->play = 1; + V->loop = 0; + + if (V->amp > 1.0f) V->amp = 1.0; + if (V->amp < 0.0f) V->amp = 0.0; + + return V; + } /* Attempt to open the named Ogg stream. */ if ((fp = fs_open_read(filename))) @@ -335,7 +472,11 @@ void audio_play(const char *filename, float a) for (V = voices; V; V = V->next) if (strcmp(V->name, filename) == 0) { - ov_raw_seek(&V->vf, 0); + if (V->cached_voice) { + V->cached_voice_start = 0; + } else { + ov_raw_seek(&V->vf, 0); + } V->amp = a; @@ -363,6 +504,15 @@ void audio_play(const char *filename, float a) } } +void audio_cache(const char *filename) +{ + struct cached_voice *CV = cached_voice_init(filename); + if (CV) { + CV->next = cached_voices; + cached_voices = CV; + } +} + /*---------------------------------------------------------------------------*/ static void audio_music_play(const char *filename) diff --git a/share/audio.h b/share/audio.h index 101de892c..6ae256cd1 100644 --- a/share/audio.h +++ b/share/audio.h @@ -6,6 +6,7 @@ void audio_init(void); void audio_free(void); void audio_play(const char *, float); +void audio_cache(const char *); void audio_music_fade_to(float, const char *); void audio_music_fade_in(float);