bananenkeyboard/Pi/main.go

166 lines
2.9 KiB
Go
Raw Normal View History

2022-10-16 15:08:02 +00:00
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))>>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]
}
}