Initial code for basic SDL2 audio engine
This commit is contained in:
commit
ae3b0695ba
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.mp3
|
||||||
|
*.ogg
|
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2020 Noah Petherbridge
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
50
README.md
Normal file
50
README.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# audio: Simple Audio Engine for Go
|
||||||
|
|
||||||
|
Package `audio` is a simple audio engine for Go that can play some music and
|
||||||
|
sound files. It currently supports an SDL2 (Mixer) driver suitable for
|
||||||
|
use on desktop systems like Linux, Mac OS and Windows, with support to load
|
||||||
|
and play music files (.ogg and .mp3 format, depending on your system libraries)
|
||||||
|
and sound effects (.wav).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
See the `examples/play/main.go` for a simple command-line media player sample
|
||||||
|
that uses the SDL2 engine.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"git.kirsle.net/go/audio/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sfx, err := sdl.New(mix.INIT_MP3 | mix.INIT_OGG)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call once at program startup.
|
||||||
|
sfx.Setup()
|
||||||
|
defer sfx.Teardown()
|
||||||
|
|
||||||
|
// Load a file from disk.
|
||||||
|
music, err := sfx.LoadMusic("filename.mp3")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play it.
|
||||||
|
music.Play(0)
|
||||||
|
|
||||||
|
// Wait until done.
|
||||||
|
for sfx.Playing() {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT.
|
28
examples/play/README.md
Normal file
28
examples/play/README.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Example: `play`
|
||||||
|
|
||||||
|
This example uses the SDL2 Mixer engine to implement a _simple_ command line
|
||||||
|
program that plays music and sound files.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
play [options] path/to/file.ogg
|
||||||
|
```
|
||||||
|
|
||||||
|
Supports file types `.ogg`, `.mp3` and `.wav`.
|
||||||
|
|
||||||
|
Default behavior calls LoadSound() or LoadMusic() using the filename given.
|
||||||
|
Use the `-binary` option to go through LoadSoundBin() or LoadMusicBin() to
|
||||||
|
test initializing it by bytes array instead.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-binary
|
||||||
|
Opens the file first as a bytes array, and feeds it to the audio engine
|
||||||
|
as binary data instead of by passing a filename on disk.
|
||||||
|
|
||||||
|
-loop <int>
|
||||||
|
Loop the audio file, default 0 will only play it once. -1 for music will
|
||||||
|
play forever.
|
||||||
|
```
|
118
examples/play/main.go
Normal file
118
examples/play/main.go
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
// Example program using the SDL2 Mix engine.
|
||||||
|
//
|
||||||
|
// Plays a music or sound file from disk.
|
||||||
|
// Usage: `play <filepath>`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.kirsle.net/go/audio/sdl"
|
||||||
|
"github.com/veandco/go-sdl2/mix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CLI flags.
|
||||||
|
var (
|
||||||
|
flagBinary bool
|
||||||
|
flagLoop int
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.BoolVar(&flagBinary, "binary", false,
|
||||||
|
"Feed the file as bytes instead of by filename on disk.")
|
||||||
|
flag.IntVar(&flagLoop, "loop", 0, "Number of times to loop the audio.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fmt.Println("Usage: play <path/to/file.mp3>")
|
||||||
|
fmt.Println("Supports .ogg, .mp3, .wav")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
sfx, err := sdl.New(mix.INIT_MP3 | mix.INIT_OGG)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sfx.Setup()
|
||||||
|
|
||||||
|
var (
|
||||||
|
filename = os.Args[len(os.Args)-1]
|
||||||
|
sound sdl.Track
|
||||||
|
)
|
||||||
|
if flagBinary {
|
||||||
|
fmt.Printf("Opening '%s' and feeding to engine as binary\n", filename)
|
||||||
|
sound = loadBinary(sfx, filename)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Playing '%s' from filesystem\n", filename)
|
||||||
|
sound = loadFilename(sfx, filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Begin playback")
|
||||||
|
sound.Play(flagLoop)
|
||||||
|
|
||||||
|
for sfx.Playing() {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
fmt.Print(".")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Done.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFilename(sfx *sdl.Engine, filename string) sdl.Track {
|
||||||
|
var (
|
||||||
|
sound sdl.Track
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
switch filepath.Ext(filename) {
|
||||||
|
case ".ogg", ".mp3":
|
||||||
|
sound, err = sfx.LoadMusic(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
case ".wav":
|
||||||
|
sound, err = sfx.LoadSound(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("Unsupported file type")
|
||||||
|
}
|
||||||
|
return sound
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads the audio file by sending the byte stream into the audio engine
|
||||||
|
// instead of having the audio engine open it from filesystem itself.
|
||||||
|
func loadBinary(sfx *sdl.Engine, filename string) sdl.Track {
|
||||||
|
bin, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sound sdl.Track
|
||||||
|
|
||||||
|
switch filepath.Ext(filename) {
|
||||||
|
case ".ogg", ".mp3":
|
||||||
|
sound, err = sfx.LoadMusicBin(bin)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
case ".wav":
|
||||||
|
sound, err = sfx.LoadSoundBin(bin)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("Unsupported file type: " + filepath.Ext(filename))
|
||||||
|
}
|
||||||
|
return sound
|
||||||
|
}
|
44
interface.go
Normal file
44
interface.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package audio
|
||||||
|
|
||||||
|
// Engine is a music and sound effects driver.
|
||||||
|
type Engine interface {
|
||||||
|
// Setup runs initialization tasks for the audio engine.
|
||||||
|
Setup() error
|
||||||
|
|
||||||
|
// Teardown runs closing tasks for the audio engine to shut down gracefully.
|
||||||
|
Teardown() error
|
||||||
|
|
||||||
|
// Playing returns a bool if something is actively playing.
|
||||||
|
// PlayingMusic and PlayingSound check specifically if music or sound
|
||||||
|
// effects are currently playing.
|
||||||
|
Playing() bool
|
||||||
|
PlayingMusic() bool
|
||||||
|
PlayingSound() bool
|
||||||
|
|
||||||
|
// StopAll stops all music and sound effects.
|
||||||
|
// StopMusic and StopSounds to selectively stop either the music or all
|
||||||
|
// sound effects, respectively.
|
||||||
|
StopAll()
|
||||||
|
StopMusic()
|
||||||
|
StopSounds()
|
||||||
|
|
||||||
|
// LoadMusic opens a music file from disk and loads it into memory.
|
||||||
|
// LoadMusicBin to load file by bytes in memory instead.
|
||||||
|
LoadMusic(filename string) (Playable, error)
|
||||||
|
LoadMusicBin(data []byte) (Playable, error)
|
||||||
|
|
||||||
|
// LoadSound opens a sound effect file.
|
||||||
|
// LoadSoundBin to load file by bytes in memory instead.
|
||||||
|
LoadSound(filename string) (Playable, error)
|
||||||
|
LoadSoundBin(data []byte) (Playable, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Playable is a music or sound effect object that can be played and managed.
|
||||||
|
type Playable interface {
|
||||||
|
Play(loops int) error
|
||||||
|
Pause() error
|
||||||
|
Stop() error
|
||||||
|
|
||||||
|
// Destroy deallocates and frees the memory.
|
||||||
|
Destroy() error
|
||||||
|
}
|
87
null/null.go
Normal file
87
null/null.go
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// Package null implements a dummy audio driver that doesn't play any audio.
|
||||||
|
package null
|
||||||
|
|
||||||
|
// Engine is a null audio engine.
|
||||||
|
type Engine struct{}
|
||||||
|
|
||||||
|
// Playable is a null music or sound effect.
|
||||||
|
type Playable struct{}
|
||||||
|
|
||||||
|
// New creates a null engine.
|
||||||
|
func New() *Engine {
|
||||||
|
return &Engine{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the null engine (do nothing).
|
||||||
|
func (e *Engine) Setup() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Teardown the null engine (do nothing).
|
||||||
|
func (e *Engine) Teardown() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Playing returns false.
|
||||||
|
func (e *Engine) Playing() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlayingMusic returns false.
|
||||||
|
func (e *Engine) PlayingMusic() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlayingSound returns false.
|
||||||
|
func (e *Engine) PlayingSound() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopAll does nothing.
|
||||||
|
func (e *Engine) StopAll() {}
|
||||||
|
|
||||||
|
// StopMusic does nothing.
|
||||||
|
func (e *Engine) StopMusic() {}
|
||||||
|
|
||||||
|
// StopSounds does nothing.
|
||||||
|
func (e *Engine) StopSounds() {}
|
||||||
|
|
||||||
|
// LoadMusic loads nothing.
|
||||||
|
func (e *Engine) LoadMusic(filename string) (Playable, error) {
|
||||||
|
return Playable{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadMusicBin loads nothing.
|
||||||
|
func (e *Engine) LoadMusicBin(data []byte) (Playable, error) {
|
||||||
|
return Playable{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSound loads nothing.
|
||||||
|
func (e *Engine) LoadSound(filename string) (Playable, error) {
|
||||||
|
return Playable{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSoundBin loads nothing.
|
||||||
|
func (e *Engine) LoadSoundBin(data []byte) (Playable, error) {
|
||||||
|
return Playable{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play nothing.
|
||||||
|
func (p Playable) Play(loops int) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pause nothing
|
||||||
|
func (p Playable) Pause() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop nothing.
|
||||||
|
func (p Playable) Stop() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy nothing.
|
||||||
|
func (p Playable) Destroy() error {
|
||||||
|
return nil
|
||||||
|
}
|
13
null_test.go
Normal file
13
null_test.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package audio_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.kirsle.net/go/audio/null"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNullEngine(t *testing.T) {
|
||||||
|
null := null.New()
|
||||||
|
null.Setup()
|
||||||
|
null.Teardown()
|
||||||
|
}
|
127
sdl/music.go
Normal file
127
sdl/music.go
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
package sdl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/veandco/go-sdl2/mix"
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Track is a music or sound effect file.
|
||||||
|
type Track struct {
|
||||||
|
isMusic bool // false = is sound effect
|
||||||
|
|
||||||
|
// If isMusic
|
||||||
|
mus *mix.Music
|
||||||
|
|
||||||
|
// Sound effect
|
||||||
|
wav *mix.Chunk
|
||||||
|
channel int
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadMusic loads a music file from disk.
|
||||||
|
func (e *Engine) LoadMusic(filename string) (Track, error) {
|
||||||
|
mus, err := mix.LoadMUS(filename)
|
||||||
|
return Track{
|
||||||
|
isMusic: true,
|
||||||
|
mus: mus,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadMusicBin loads a music file from bytes data.
|
||||||
|
func (e *Engine) LoadMusicBin(data []byte) (Track, error) {
|
||||||
|
// Create an SDL RWOps from the binary.
|
||||||
|
rw, err := sdl.RWFromMem(data)
|
||||||
|
if err != nil {
|
||||||
|
return Track{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mus, err := mix.LoadMUSRW(rw, 0)
|
||||||
|
return Track{
|
||||||
|
isMusic: true,
|
||||||
|
mus: mus,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSound loads a wave file from disk.
|
||||||
|
func (e *Engine) LoadSound(filename string) (Track, error) {
|
||||||
|
wav, err := mix.LoadWAV(filename)
|
||||||
|
return Track{
|
||||||
|
isMusic: false,
|
||||||
|
wav: wav,
|
||||||
|
channel: -1,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSoundBin loads a wave file from bytes data.
|
||||||
|
func (e *Engine) LoadSoundBin(data []byte) (Track, error) {
|
||||||
|
// Create an SDL RWOps from the binary.
|
||||||
|
rw, err := sdl.RWFromMem(data)
|
||||||
|
if err != nil {
|
||||||
|
return Track{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
wav, err := mix.LoadWAVRW(rw, false)
|
||||||
|
return Track{
|
||||||
|
isMusic: false,
|
||||||
|
wav: wav,
|
||||||
|
channel: -1,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play the track.
|
||||||
|
func (t *Track) Play(loops int) error {
|
||||||
|
if t.isMusic {
|
||||||
|
return t.mus.Play(loops)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize the `loops` value for sound effects to work around
|
||||||
|
// a quirk in the SDL mixer between Music and Sound behaviors:
|
||||||
|
//
|
||||||
|
// For music:
|
||||||
|
// loops=0 plays it one time
|
||||||
|
// loops=1 plays it one time
|
||||||
|
// loops=2 plays it twice
|
||||||
|
// For sounds:
|
||||||
|
// loops=0 plays it one time
|
||||||
|
// loops=1 plays it twice!
|
||||||
|
// loops=2 plays it three times!
|
||||||
|
//
|
||||||
|
// For both, a loops of -1 plays it on an infinite loop. So to make
|
||||||
|
// the API consistent on our end, subtract 1 from a Sound loop only
|
||||||
|
// when the given value is >= 1 itself.
|
||||||
|
if loops > 0 {
|
||||||
|
loops--
|
||||||
|
}
|
||||||
|
channel, err := t.wav.Play(-1, loops)
|
||||||
|
t.channel = channel
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pause the track.
|
||||||
|
func (t Track) Pause() error {
|
||||||
|
if t.isMusic {
|
||||||
|
mix.PauseMusic()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
mix.Pause(t.channel)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the track.
|
||||||
|
func (t Track) Stop() error {
|
||||||
|
if t.isMusic {
|
||||||
|
mix.HaltMusic()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
mix.HaltChannel(t.channel)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the track.
|
||||||
|
func (t Track) Destroy() error {
|
||||||
|
if t.isMusic {
|
||||||
|
t.mus.Free()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
t.wav.Free()
|
||||||
|
return nil
|
||||||
|
}
|
78
sdl/sdl.go
Normal file
78
sdl/sdl.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
// Package sdl implements an audio engine using libSDL2.
|
||||||
|
package sdl
|
||||||
|
|
||||||
|
import "github.com/veandco/go-sdl2/mix"
|
||||||
|
|
||||||
|
// Engine is the SDL2 audio engine.
|
||||||
|
type Engine struct {
|
||||||
|
initFlags int
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
// mix.INIT_MP3
|
||||||
|
// mix.INIT_OGG
|
||||||
|
// mix.INIT_FLAC
|
||||||
|
// mix.INIT_MOD
|
||||||
|
func New(flags int) (*Engine, error) {
|
||||||
|
return &Engine{
|
||||||
|
initFlags: flags,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup initializes SDL2 Mixer.
|
||||||
|
func (e *Engine) Setup() error {
|
||||||
|
// Initialize SDL2 mixer.
|
||||||
|
if err := mix.Init(e.initFlags); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user