From 60f96104a26d1931cc66d670e7c0a73c676ced5d Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 27 Aug 2023 21:34:02 +0200 Subject: [PATCH] [wip] add audio controller --- audio_controller.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ main.go | 15 ++++++++++++--- 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 audio_controller.go diff --git a/audio_controller.go b/audio_controller.go new file mode 100644 index 0000000..bca8220 --- /dev/null +++ b/audio_controller.go @@ -0,0 +1,45 @@ +package main + +import ( + "encoding/binary" + "github.com/gordonklaus/portaudio" + "github.com/labstack/echo/v4" + "net/http" +) + +func chk(err error) { + if err != nil { + panic(err) + } +} + +func audioController(c echo.Context) error { + if audioIsInitialized == false { + portaudio.Initialize() + defer portaudio.Terminate() + audioBuffer = make([]float32, audioSampleRate*audioSeconds) + stream, err := portaudio.OpenDefaultStream(1, 0, audioSampleRate, len(audioBuffer), func(in []float32) { + for i := range audioBuffer { + audioBuffer[i] = in[i] + } + }) + chk(err) + chk(stream.Start()) + defer stream.Close() + } + + flusher, _ := c.Response().Writer.(http.Flusher) + + c.Response().Header().Set("Connection", "Keep-Alive") + c.Response().Header().Set("Access-Control-Allow-Origin", "*") + c.Response().Header().Set("X-Content-Type-Options", "nosniff") + c.Response().Header().Set("Transfer-Encoding", "chunked") + c.Response().Header().Set("Content-Type", "audio/wave") + + for true { + binary.Write(c.Response().Writer, binary.BigEndian, &audioBuffer) + flusher.Flush() // Trigger "chunked" encoding and send a chunk... + } + + return nil +} diff --git a/go.mod b/go.mod index a00f573..2675969 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/daaku/go.zipexe v1.0.2 // indirect github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/gordonklaus/portaudio v0.0.0-20230709114228-aafa478834f5 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/jezek/xgb v1.1.0 // indirect github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 // indirect diff --git a/go.sum b/go.sum index 55e33d8..3411f68 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 h1:VLEKvjGJYAMCXw0/3 github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/gordonklaus/portaudio v0.0.0-20230709114228-aafa478834f5 h1:5AlozfqaVjGYGhms2OsdUyfdJME76E6rx5MdGpjzZpc= +github.com/gordonklaus/portaudio v0.0.0-20230709114228-aafa478834f5/go.mod h1:WY8R6YKlI2ZI3UyzFk7P6yGSuS+hFwNtEzrexRyD7Es= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/main.go b/main.go index f210e5a..71a4631 100644 --- a/main.go +++ b/main.go @@ -12,14 +12,21 @@ import ( "os" ) +const ( + audioSampleRate = 44100 + audioSeconds = 2 +) + var ( templates map[string]*template.Template //go:embed static staticFiles embed.FS //go:embed views/layout views/page - views embed.FS - config Config - actions Actions + views embed.FS + config Config + actions Actions + audioBuffer []float32 + audioIsInitialized bool ) func main() { @@ -40,6 +47,7 @@ func main() { } config = value + audioIsInitialized = false e.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) { if config.Server.Auth.Username == "" && config.Server.Auth.Password == "" { return true, nil @@ -61,6 +69,7 @@ func main() { e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", assetHandler))) e.GET("/", homeController) e.GET("/ws", wsController) + e.GET("/audio", audioController) e.Logger.Fatal(e.Start(config.Server.Listen)) }