2020-04-29 05:54:51 +00:00
|
|
|
// Package sdl implements an audio engine using libSDL2.
|
|
|
|
package sdl
|
|
|
|
|
2023-03-10 06:55:53 +00:00
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/veandco/go-sdl2/mix"
|
|
|
|
)
|
2020-04-29 05:54:51 +00:00
|
|
|
|
|
|
|
// Engine is the SDL2 audio engine.
|
|
|
|
type Engine struct {
|
|
|
|
initFlags int
|
2023-03-10 06:55:53 +00:00
|
|
|
|
|
|
|
// Keep track of which SDL channel numbers are ACTUALLY playing sound
|
|
|
|
// effects right now, and watch for when the channels are finished.
|
|
|
|
channelMu sync.RWMutex
|
|
|
|
channelsPlaying map[int]*Track
|
2020-04-29 05:54:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// New initializes an SDL2 Mixer for the audio engine.
|
|
|
|
//
|
|
|
|
// Pass the SDL2 Mixer flags for its initialization. The flags are an OR'd
|
|
|
|
// value made up of:
|
2023-03-10 06:55:53 +00:00
|
|
|
//
|
|
|
|
// mix.INIT_MP3
|
|
|
|
// mix.INIT_OGG
|
|
|
|
// mix.INIT_FLAC
|
|
|
|
// mix.INIT_MOD
|
2020-04-29 05:54:51 +00:00
|
|
|
func New(flags int) (*Engine, error) {
|
|
|
|
return &Engine{
|
2023-03-10 06:55:53 +00:00
|
|
|
initFlags: flags,
|
|
|
|
channelsPlaying: map[int]*Track{},
|
2020-04-29 05:54:51 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup initializes SDL2 Mixer.
|
|
|
|
func (e *Engine) Setup() error {
|
|
|
|
// Initialize SDL2 mixer.
|
|
|
|
if err := mix.Init(e.initFlags); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-03-10 06:55:53 +00:00
|
|
|
// Subscribe to sound effect channels finishing.
|
|
|
|
mix.ChannelFinished(func(channel int) {
|
|
|
|
_ = e.unsetPlaying(channel)
|
|
|
|
})
|
|
|
|
|
2020-04-29 05:54:51 +00:00
|
|
|
// Open the audio mixer.
|
|
|
|
// the '2' is stereo (two channels), '1' would be mono.
|
|
|
|
// 4096 is the chunk size.
|
|
|
|
// https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer_11.html
|
|
|
|
return mix.OpenAudio(mix.DEFAULT_FREQUENCY, mix.DEFAULT_FORMAT, 2, 4096)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Playing returns if either music or sounds are currently playing.
|
|
|
|
func (e *Engine) Playing() bool {
|
|
|
|
if mix.PlayingMusic() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return mix.Playing(-1) > 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// PlayingMusic returns if music is currently playing.
|
|
|
|
func (e *Engine) PlayingMusic() bool {
|
|
|
|
return mix.PlayingMusic()
|
|
|
|
}
|
|
|
|
|
|
|
|
// PlayingSound returns if sounds are playing.
|
|
|
|
func (e *Engine) PlayingSound() bool {
|
|
|
|
return mix.Playing(-1) > 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// StopAll stops all music and sounds.
|
|
|
|
func (e *Engine) StopAll() {
|
|
|
|
e.StopMusic()
|
|
|
|
e.StopSounds()
|
|
|
|
}
|
|
|
|
|
|
|
|
// StopMusic stops all music.
|
|
|
|
func (e *Engine) StopMusic() {
|
|
|
|
mix.HaltMusic()
|
|
|
|
}
|
|
|
|
|
|
|
|
// StopSounds stops all sounds.
|
|
|
|
func (e *Engine) StopSounds() {
|
|
|
|
mix.HaltChannel(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Teardown closes the SDL mixer.
|
|
|
|
func (e *Engine) Teardown() error {
|
|
|
|
mix.CloseAudio()
|
|
|
|
mix.Quit()
|
|
|
|
return nil
|
|
|
|
}
|