package main import ( "github.com/faiface/beep" "github.com/faiface/beep/effects" "github.com/faiface/beep/speaker" "github.com/faiface/beep/wav" "github.com/tarm/serial" "log" "math" "os" "sync" "time" ) var sounds = []*beep.Buffer{ mustLoadStream("./mini_grand/mini_grand-001.wav"), mustLoadStream("./mini_grand/mini_grand-003.wav"), mustLoadStream("./mini_grand/mini_grand-005.wav"), mustLoadStream("./mini_grand/mini_grand-006.wav"), mustLoadStream("./mini_grand/mini_grand-008.wav"), mustLoadStream("./mini_grand/mini_grand-010.wav"), mustLoadStream("./mini_grand/mini_grand-012.wav"), mustLoadStream("./mini_grand/mini_grand-013.wav"), } func mustLoadStream(p string) *beep.Buffer { f, err := os.Open(p) if err != nil { log.Fatal(err) } defer f.Close() streamer, format, err := wav.Decode(f) if err != nil { log.Fatal(err) } defer streamer.Close() newFormat := format newFormat.SampleRate = format.SampleRate / 4 resample := beep.Resample(4, format.SampleRate, newFormat.SampleRate, streamer) buffer := beep.NewBuffer(newFormat) buffer.Append(resample) return buffer } type soundWorker struct { buffer *beep.Buffer ctrl *beep.Ctrl volume *effects.Volume isRunning bool isStopping bool forceEnd bool mtx sync.Mutex } func (w *soundWorker) End() { w.isStopping = true w.mtx.Lock() defer w.mtx.Unlock() i := 1 for w.isRunning { if i >= 80 || w.forceEnd { break } w.volume.Volume = float64(1) / math.Pow(10, float64(i)) i++ } w.isRunning = false w.isStopping = false w.forceEnd = false w.ctrl.Paused = true } func (w *soundWorker) Start() { if w.isRunning { w.forceEnd = true } w.mtx.Lock() defer w.mtx.Unlock() w.isRunning = true w.ctrl.Streamer.(beep.StreamSeeker).Seek(0) w.volume.Volume = 1 w.ctrl.Paused = false } func main() { config := &serial.Config{ Name: "/dev/ttyS0", Baud: 115200, Size: 8, } stream, err := serial.OpenPort(config) if err != nil { log.Fatal(err) } format := sounds[0].Format() if err := speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/100)); err != nil { return } var soundWorkers []*soundWorker mixer := beep.Mixer{} for _, buffer := range sounds { c := &beep.Ctrl{ Streamer: buffer.Streamer(0, buffer.Len()), Paused: true, } volume := &effects.Volume{ Streamer: c, Base: 2, Volume: 1, } mixer.Add(volume) soundWorkers = append(soundWorkers, &soundWorker{ buffer: buffer, ctrl: c, volume: volume, }) } speaker.Play(&mixer) c := make(chan byte) go func() { for b := range c { for i, w := range soundWorkers { setStop := (b&(1<>i == 0 if w.isRunning && !w.isStopping && setStop { w.End() } if !w.isRunning && !setStop { w.Start() } } } }() for { buf := make([]byte, 1) _, err := stream.Read(buf) if err != nil { log.Fatal(err) } c <- buf[0] } }