From fed1672c0d6483973c1aeb8978fdb3f5f7896058 Mon Sep 17 00:00:00 2001 From: Nonoo Date: Tue, 20 Oct 2020 15:23:12 +0200 Subject: [PATCH] Add audio playback --- audio.go | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ audiostream.go | 2 +- main.go | 44 +------------------- 3 files changed, 112 insertions(+), 43 deletions(-) create mode 100644 audio.go diff --git a/audio.go b/audio.go new file mode 100644 index 0000000..500d322 --- /dev/null +++ b/audio.go @@ -0,0 +1,109 @@ +package main + +import ( + "bytes" + + "github.com/akosmarton/papipes" + "github.com/nonoo/kappanhang/log" +) + +type audioStruct struct { + source papipes.Source + sink papipes.Sink + + // Send to this channel to play audio. + play chan []byte + rec chan []byte + + playBuf *bytes.Buffer + canPlay chan bool +} + +var audio audioStruct + +func (a *audioStruct) playLoop() { + for { + <-a.canPlay + + d := make([]byte, a.playBuf.Len()) + bytesToWrite, err := a.playBuf.Read(d) + if err == nil { + for { + written, err := a.source.Write(d) + if err != nil { + log.Error(err) + break + } + bytesToWrite -= written + if bytesToWrite == 0 { + break + } + d = d[written:] + } + } else { + log.Error(err) + } + } +} + +func (a *audioStruct) loop() { + go a.playLoop() + + for { + select { + case d := <-a.play: + a.playBuf.Write(d) + + select { + case a.canPlay <- true: + default: + } + } + } +} + +func (a *audioStruct) init() { + a.source.Name = "kappanhang" + a.source.Filename = "/tmp/kappanhang.source" + a.source.Rate = 48000 + a.source.Format = "s16le" + a.source.Channels = 1 + a.source.SetProperty("device.buffering.buffer_size", 1920*5) + a.source.SetProperty("device.description", "kappanhang input") + + a.sink.Name = "kappanhang" + a.sink.Filename = "/tmp/kappanhang.sink" + a.sink.Rate = 48000 + a.sink.Format = "s16le" + a.sink.Channels = 1 + a.sink.SetProperty("device.buffering.buffer_size", 1920*5) + a.sink.SetProperty("device.description", "kappanhang output") + + if err := a.source.Open(); err != nil { + exit(err) + } + + if err := a.sink.Open(); err != nil { + exit(err) + } + + a.playBuf = bytes.NewBuffer([]byte{}) + a.play = make(chan []byte) + a.canPlay = make(chan bool) + a.rec = make(chan []byte) + go a.loop() +} + +func (a *audioStruct) deinit() { + if a.source.IsOpen() { + if err := a.source.Close(); err != nil { + log.Error(err) + } + } + + if a.sink.IsOpen() { + if err := a.sink.Close(); err != nil { + log.Error(err) + } + } +} diff --git a/audiostream.go b/audiostream.go index cbfa236..1a3b9bc 100644 --- a/audiostream.go +++ b/audiostream.go @@ -91,7 +91,7 @@ func (s *audioStream) handleRxSeqBufEntry(e seqBufEntry) { s.lastReceivedAudioSeq = gotSeq s.receivedAudio = true - // TODO: audioPipes.source.Write() + audio.play <- e.data } func (s *audioStream) handleAudioPacket(r []byte) { diff --git a/main.go b/main.go index 8ec771a..8ba08d4 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,6 @@ import ( "os/signal" "syscall" - "github.com/akosmarton/papipes" "github.com/nonoo/kappanhang/log" ) @@ -14,11 +13,6 @@ var streams struct { audio audioStream } -var audioPipes struct { - source papipes.Source - sink papipes.Sink -} - func exit(err error) { if err != nil { log.Error(err.Error()) @@ -26,18 +20,7 @@ func exit(err error) { streams.audio.sendDisconnect() streams.control.sendDisconnect() - - if audioPipes.source.IsOpen() { - if err := audioPipes.source.Close(); err != nil { - log.Error(err) - } - } - - if audioPipes.sink.IsOpen() { - if err := audioPipes.sink.Close(); err != nil { - log.Error(err) - } - } + audio.deinit() log.Print("exiting") if err == nil { @@ -61,30 +44,7 @@ func main() { log.Print("kappanhang by Norbert Varga HA2NON https://github.com/nonoo/kappanhang") parseArgs() - audioPipes.source.Name = "kappanhang" - audioPipes.source.Filename = "/tmp/kappanhang.source" - audioPipes.source.Rate = 48000 - audioPipes.source.Format = "s16le" - audioPipes.source.Channels = 1 - audioPipes.source.SetProperty("device.buffering.buffer_size", 1920*5) - audioPipes.source.SetProperty("device.description", "kappanhang input") - - audioPipes.sink.Name = "kappanhang" - audioPipes.sink.Filename = "/tmp/kappanhang.sink" - audioPipes.sink.Rate = 48000 - audioPipes.sink.Format = "s16le" - audioPipes.sink.Channels = 1 - audioPipes.sink.SetProperty("device.buffering.buffer_size", 1920*5) - audioPipes.sink.SetProperty("device.description", "kappanhang output") - - if err := audioPipes.source.Open(); err != nil { - exit(err) - } - - if err := audioPipes.sink.Open(); err != nil { - exit(err) - } - + audio.init() streams.audio.init() streams.control.init()