Skip to main content

forge-audio-pool

Add fire-and-forget audio playback with a source pool and volume fading for click-free start/stop transitions.

Ir a la instalación

Datos de origen

Repositorio
Nebulavenus/forge-gpu
Última actividad en el origen
16 de marzo de 2026 a las 02:28
Idioma detectado de SKILL.md
inglés
Estrellas
38
Forks
7

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
forge-audio-pool
description
Add fire-and-forget audio playback with a source pool and volume fading for click-free start/stop transitions.
trigger
Use when someone needs polyphonic sound effects, fire-and-forget audio, one-shot playback, or fade-in/fade-out on audio sources.
# forge-audio-pool Add fire-and-forget sound effect playback using `ForgeAudioPool` and smooth volume transitions using the fade envelope on `ForgeAudioSource`. Based on [Audio Lesson 02](../../../lessons/audio/02-sound-effects/). ## When to use - Playing the same sound multiple times with overlap (polyphony) - One-shot sound effects that should auto-clean-up when finished - Starting or stopping sounds without audible clicks (fade-in / fade-out) - Ambient loops that toggle smoothly with a volume ramp ## Source pool pattern ```c #include "audio/forge_audio.h" /* In app_state */ ForgeAudioPool pool; ForgeAudioBuffer sfx_buffer; /* In SDL_AppInit */ forge_audio_pool_init(&pool); forge_audio_load_wav("assets/audio/impact.wav", &sfx_buffer); /* Fire-and-forget: each call allocates a new slot (up to 32) */ int slot = forge_audio_pool_play(&pool, &sfx_buffer, 1.0f, false); if (slot < 0) { SDL_Log("Pool full — sound dropped"); } /* In SDL_AppIterate — mix all active sources, reclaim finished slots */ SDL_memset(scratch, 0, samples * sizeof(float)); forge_audio_pool_mix(&pool, scratch, frames_needed); /* Stop everything */ forge_audio_pool_stop_all(&pool); ``` The pool scans for the first slot with `playing == false`. Non-looping sources auto-stop at buffer end; the slot is then reusable by the next `pool_play()`. ## Fade envelope pattern ```c /* Fade fields on ForgeAudioSource (initialized by forge_audio_source_create): * fade_volume = 1.0 (current multiplier) * fade_target = 1.0 (destination) * fade_rate = 0.0 (change per second, 0 = no fade) */ /* Start a fade to any target */ forge_audio_source_fade(src, 0.5f, 2.0f); /* fade to 50% over 2 seconds */ /* Convenience: fade in from silence (sets fade_volume=0, starts playback) */ forge_audio_source_fade_in(src, 0.5f); /* Convenience: fade out to zero (auto-stops when complete) */ forge_audio_source_fade_out(src, 1.0f); /* MUST call once per frame to advance the ramp */ forge_audio_source_fade_update(src, dt); ``` The fade multiplier is applied on top of `volume * pan` during `forge_audio_source_mix()`. Default `fade_volume=1.0` means existing code from Lesson 01 behaves identically. ## Combining pool + fade For pool sources that need fade control, get the source pointer after play: ```c int slot = forge_audio_pool_play(&pool, &buffer, 1.0f, true); if (slot >= 0) { ForgeAudioSource *src = forge_audio_pool_get(&pool, slot); forge_audio_source_fade_in(src, 0.3f); } /* Update fades on all pool sources each frame */ for (int i = 0; i < FORGE_AUDIO_POOL_MAX_SOURCES; i++) { if (pool.sources[i].playing) { forge_audio_source_fade_update(&pool.sources[i], dt); } } ``` ## Ambient loop with fade toggle For a single looping source managed outside the pool (direct fade control): ```c /* In app_state */ ForgeAudioSource ambient; bool ambient_active; /* Toggle on key press */ if (ambient_active) { forge_audio_source_fade_out(&ambient, fade_duration); ambient_active = false; } else { if (!ambient.playing) forge_audio_source_reset(&ambient); forge_audio_source_fade_in(&ambient, fade_duration); ambient_active = true; } ``` ## Common mistakes - **Forgetting `fade_update`** — The fade does not advance automatically. Call `forge_audio_source_fade_update(src, dt)` once per frame for every source that might be fading. - **Calling fade_update per mix call** — Call it per frame, not per mix invocation. The rate is in units per second, scaled by `dt`. - **Not zeroing the mix buffer** — `forge_audio_pool_mix()` is additive. Always `memset(out, 0, ...)` before the first mix call each frame. - **Ignoring pool_play return value** — Returns -1 when full. Decide whether to drop the sound or steal an existing slot. ## API reference | Function | Purpose | |---|---| | `forge_audio_pool_init` | Zero all 32 slots | | `forge_audio_pool_play` | Play buffer in first idle slot → index or -1 | | `forge_audio_pool_get` | Get source pointer at index → `ForgeAudioSource*` or NULL | | `forge_audio_pool_mix` | Mix active sources, reclaim finished | | `forge_audio_pool_stop_all` | Stop everything | | `forge_audio_pool_active_count` | Count of playing sources | | `forge_audio_source_fade` | Start fade toward target over duration | | `forge_audio_source_fade_in` | 0→1 fade, starts playback | | `forge_audio_source_fade_out` | Current→0 fade, auto-stops | | `forge_audio_source_fade_update` | Advance fade by dt seconds |
Ver en GitHub