Basic audio manager setup.
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
package game
|
||||
|
||||
import rl "vendor:raylib"
|
||||
|
||||
Fade_State :: enum {
|
||||
None,
|
||||
In,
|
||||
Out,
|
||||
}
|
||||
|
||||
// setup sound IDs so gameplay code never
|
||||
// touches raw Raylib sound handles
|
||||
Sound_ID :: enum {
|
||||
Ball_Collision,
|
||||
Score_Goal,
|
||||
UI_Select,
|
||||
UI_Confirm,
|
||||
}
|
||||
|
||||
Audio_Manager :: struct {
|
||||
sounds: map[Sound_ID]rl.Sound,
|
||||
music: rl.Music,
|
||||
music_loaded: bool,
|
||||
|
||||
sfx_vol: f32, // User SFX volume setting
|
||||
user_music_vol: f32, // User Music volume setting
|
||||
current_music_vol: f32, // Live interpolated output volume
|
||||
|
||||
// Runtime Fade State
|
||||
fade_state: Fade_State,
|
||||
fade_elapsed_sec: f32,
|
||||
fade_duration_sec: f32,
|
||||
}
|
||||
// ------------------------------------------------------------------------------
|
||||
// Lifecycle procs
|
||||
// ------------------------------------------------------------------------------
|
||||
audio_init :: proc(audio: ^Audio_Manager) {
|
||||
rl.InitAudioDevice()
|
||||
audio.sounds = make(map[Sound_ID]rl.Sound)
|
||||
|
||||
// Load SFX
|
||||
audio.sfx_vol = 0.5
|
||||
audio.sounds[.UI_Select] = rl.LoadSound("assets/audio/ui/select.ogg")
|
||||
audio.sounds[.Ball_Collision] = rl.LoadSound("assets/audio/gameplay/ballhit.ogg")
|
||||
|
||||
// Load Music Stream
|
||||
audio.user_music_vol = 0.1
|
||||
audio.current_music_vol = 0.0
|
||||
audio.fade_state = .None
|
||||
audio.music = rl.LoadMusicStream("assets/audio/gameplay/music/track_1.wav")
|
||||
audio.music_loaded = true
|
||||
rl.SetMusicVolume(audio.music, audio.current_music_vol)
|
||||
}
|
||||
|
||||
audio_update :: proc(audio: ^Audio_Manager, dt: f32) {
|
||||
if !audio.music_loaded do return
|
||||
|
||||
// Process Fade if the audio state machine requires
|
||||
if audio.fade_state != .None {
|
||||
audio.fade_elapsed_sec += dt
|
||||
// convert elapsed seconds over target seconds into a 0.0 -> 1.0 percentage
|
||||
progress_pct := clamp(audio.fade_elapsed_sec / audio.fade_duration_sec, 0.0, 1.0)
|
||||
|
||||
#partial switch audio.fade_state {
|
||||
case .In:
|
||||
audio.current_music_vol = rl.Lerp(0.0, audio.user_music_vol, progress_pct)
|
||||
// progress is 100% or more stop fading in music
|
||||
if progress_pct >= 1.0 do audio.fade_state = .None
|
||||
|
||||
case .Out:
|
||||
audio.current_music_vol = rl.Lerp(audio.user_music_vol, 0.0, progress_pct)
|
||||
// progress is 100% or more stop fading out music and stop the stream
|
||||
if progress_pct >= 1.0 {
|
||||
audio.fade_state = .None
|
||||
rl.StopMusicStream(audio.music)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not fading, output matches the user setting directly
|
||||
audio.current_music_vol = audio.user_music_vol
|
||||
}
|
||||
|
||||
rl.SetMusicVolume(audio.music, audio.current_music_vol)
|
||||
|
||||
// keep audio stream buffer fed
|
||||
if rl.IsMusicStreamPlaying(audio.music) {
|
||||
rl.UpdateMusicStream(audio.music)
|
||||
}
|
||||
}
|
||||
|
||||
audio_manager_quit :: proc(audio: ^Audio_Manager) {
|
||||
for _, sound in audio.sounds {
|
||||
rl.UnloadSound(sound)
|
||||
}
|
||||
delete(audio.sounds)
|
||||
rl.UnloadMusicStream(audio.music)
|
||||
rl.CloseAudioDevice()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Utilities
|
||||
// ------------------------------------------------------------------------------
|
||||
audio_play_music :: proc(audio: ^Audio_Manager) {
|
||||
if audio.music_loaded {
|
||||
// Only trigger start if it isn't playing already
|
||||
if !rl.IsMusicStreamPlaying(audio.music) {
|
||||
rl.PlayMusicStream(audio.music)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
audio_stop_music :: proc(audio: ^Audio_Manager) {
|
||||
if audio.music_loaded && rl.IsMusicStreamPlaying(audio.music) {
|
||||
rl.StopMusicStream(audio.music)
|
||||
}
|
||||
}
|
||||
|
||||
audio_play_sfx :: proc(audio: ^Audio_Manager, id: Sound_ID) {
|
||||
if sound, ok := audio.sounds[id]; ok {
|
||||
rl.SetSoundVolume(sound, audio.sfx_vol)
|
||||
rl.PlaySound(sound)
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Audio Fading
|
||||
// ------------------------------------------------------------------------------
|
||||
audio_fade_in :: proc(audio: ^Audio_Manager, duration: f32 = 1.0) {
|
||||
if !audio.music_loaded do return
|
||||
|
||||
if !rl.IsMusicStreamPlaying(audio.music) {
|
||||
rl.PlayMusicStream(audio.music)
|
||||
}
|
||||
|
||||
audio.fade_state = .In
|
||||
audio.fade_duration_sec = max(0.001, duration)
|
||||
audio.fade_elapsed_sec = 0.0
|
||||
audio.current_music_vol = 0.0
|
||||
rl.SetMusicVolume(audio.music, 0.0)
|
||||
}
|
||||
|
||||
audio_fade_out :: proc(audio: ^Audio_Manager, duration: f32 = 1.0) {
|
||||
if !audio.music_loaded || !rl.IsMusicStreamPlaying(audio.music) do return
|
||||
|
||||
audio.fade_state = .Out
|
||||
audio.fade_duration_sec = max(0.001, duration)
|
||||
audio.fade_elapsed_sec = 0.0
|
||||
}
|
||||
Reference in New Issue
Block a user