54 lines
1.2 KiB
Go
54 lines
1.2 KiB
Go
//go:build linux
|
|
|
|
package audio
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
)
|
|
|
|
// pwEngine plays pre-rendered WAVs by spawning pw-play per effect
|
|
type pwEngine struct {
|
|
dir string
|
|
files [EffectCount]string
|
|
}
|
|
|
|
// NewEngine synthesizes effect WAVs into a temp dir. Falls back to a silent
|
|
// engine when pw-play is unavailable — game remains playable without audio
|
|
func NewEngine() Engine {
|
|
if _, err := exec.LookPath("pw-play"); err != nil {
|
|
return nullEngine{}
|
|
}
|
|
dir, err := os.MkdirTemp("", "symph-sfx-")
|
|
if err != nil {
|
|
return nullEngine{}
|
|
}
|
|
e := &pwEngine{dir: dir}
|
|
for fx := EffectNone + 1; fx < EffectCount; fx++ {
|
|
path := filepath.Join(dir, fmt.Sprintf("fx-%d.wav", fx))
|
|
if err := os.WriteFile(path, wavBytes(synth(effectSegs[fx])), 0o644); err != nil {
|
|
os.RemoveAll(dir)
|
|
return nullEngine{}
|
|
}
|
|
e.files[fx] = path
|
|
}
|
|
return e
|
|
}
|
|
|
|
// Play spawns pw-play detached; process reaped asynchronously
|
|
func (e *pwEngine) Play(fx Effect) {
|
|
if fx == EffectNone || fx >= EffectCount || e.files[fx] == "" {
|
|
return
|
|
}
|
|
cmd := exec.Command("pw-play", "--volume", "0.7", e.files[fx])
|
|
if err := cmd.Start(); err == nil {
|
|
go cmd.Wait()
|
|
}
|
|
}
|
|
|
|
func (e *pwEngine) Close() {
|
|
os.RemoveAll(e.dir)
|
|
}
|