doodle/pkg/sound/sound_sdl.go

111 lines
2.2 KiB
Go

//go:build !js && !wasm
// +build !js,!wasm
package sound
import (
"path/filepath"
"sync"
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"git.kirsle.net/go/audio"
"git.kirsle.net/go/audio/sdl"
"github.com/veandco/go-sdl2/mix"
)
// SDL engine globals.
var (
engine *sdl.Engine
// Cache of loaded music and sound effects.
music = map[string]*sdl.Track{}
sounds = map[string]*sdl.Track{}
mu sync.RWMutex
)
// Initialize SDL2 Audio at startup.
func init() {
eng, err := sdl.New(mix.INIT_MP3 | mix.INIT_OGG)
if err != nil {
log.Error("sound.init(): error initializing SDL2 audio: %s", err)
return
}
err = eng.Setup()
if err != nil {
log.Error("sound.init(): error setting up SDL2 audio: %s", err)
return
}
engine = eng
Enabled = true
}
// LoadMusic loads filename from the MusicRoot into the global music cache.
// If the music is already loaded, does nothing.
func LoadMusic(filename string) audio.Playable {
if engine == nil || !Enabled {
return nil
}
// Check if the music is already loaded.
mu.RLock()
mus, ok := music[filename]
mu.RUnlock()
if ok {
return mus
}
// Load the music in.
track, err := engine.LoadMusic(filepath.Join(MusicRoot, filename))
if err != nil {
log.Error("sound.LoadMusic: failed to load file %s: %s", filename, err)
return nil
}
mu.Lock()
music[filename] = &track
mu.Unlock()
return &track
}
// LoadSound loads filename from the SoundRoot into the global SFX cache.
// If the sound is already loaded, does nothing.
func LoadSound(filename string) audio.Playable {
if engine == nil || !Enabled {
return nil
}
// Check if the music is already loaded.
mu.RLock()
sfx, ok := sounds[filename]
mu.RUnlock()
if ok {
return sfx
}
// Load the sound in.
log.Info("Loading sound: %s", filename)
track, err := engine.LoadSound(filepath.Join(SoundRoot, filename))
if err != nil {
log.Error("sound.LoadSound: failed to load file %s: %s", filename, err)
return nil
}
mu.Lock()
sounds[filename] = &track
mu.Unlock()
return &track
}
// PlaySound plays the named sound. It will de-duplicate if the same sound is already playing.
func PlaySound(filename string) {
log.Debug("Play sound: %s", filename)
sound := LoadSound(filename)
if sound != nil && !sound.Playing() {
sound.Play(1)
}
}