This commit is contained in:
Daniel 2024-08-04 23:32:46 -04:00
parent 358b7c8754
commit 019c946c55
6 changed files with 66 additions and 344 deletions

View file

@ -1,19 +1,15 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"io"
"time" "time"
"github.com/gopxl/beep" "github.com/hajimehoshi/oto"
"github.com/gopxl/beep/mp3" "github.com/tosone/minimp3"
"github.com/gopxl/beep/speaker"
"github.com/gopxl/beep/wav"
) )
type Player struct { type Player struct {
rate beep.SampleRate ctx *oto.Context
} }
func NewPlayer() *Player { func NewPlayer() *Player {
@ -22,38 +18,53 @@ func NewPlayer() *Player {
return p return p
} }
func (p *Player) initSpeaker(rate beep.SampleRate) { func (p *Player) initOto(samp, channels int) error {
if p.rate != rate { if p.ctx != nil {
speaker.Init(rate, rate.N(time.Second/10)) return nil
} }
var err error
if p.ctx, err = oto.NewContext(samp, channels, 2, 1024); err != nil {
return err
}
return nil
}
func (p *Player) playMP3(audio []byte) error {
var dec *minimp3.Decoder
var data []byte
var err error
if dec, data, err = minimp3.DecodeFull(audio); err != nil {
return err
}
err = p.initOto(dec.SampleRate, dec.Channels)
if err != nil {
return err
}
var player = p.ctx.NewPlayer()
player.Write(data)
<-time.After(time.Second)
dec.Close()
if err = player.Close(); err != nil {
return err
}
return nil
} }
func (p *Player) Play(audio []byte, mimeType string) error { func (p *Player) Play(audio []byte, mimeType string) error {
var streamer beep.StreamCloser
var err error
var format beep.Format
r := io.NopCloser(bytes.NewBuffer(audio))
switch mimeType { switch mimeType {
case "audio/mpeg": case "audio/mpeg":
streamer, format, err = mp3.Decode(r) return p.playMP3(audio)
if err != nil {
return err
}
defer streamer.Close()
p.initSpeaker(format.SampleRate)
case "audio/wav": case "audio/wav":
streamer, format, err = wav.Decode(r)
if err != nil {
return err
}
defer streamer.Close()
p.initSpeaker(format.SampleRate)
default: default:
return fmt.Errorf("unknown format %s", mimeType) return fmt.Errorf("unknown format %s", mimeType)
} }
speaker.Play(streamer)
return nil return nil
} }

View file

@ -105,7 +105,6 @@ func main() {
err := play.Play(v.Call.Audio, v.Call.AudioType) err := play.Play(v.Call.Audio, v.Call.AudioType)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
os.WriteFile("failed.mp3", v.Call.Audio, 0644)
} }
case *pb.Message_Notification: case *pb.Message_Notification:
log.Println(v.Notification.Msg) log.Println(v.Notification.Msg)

10
go.mod
View file

@ -12,9 +12,12 @@ require (
github.com/google/uuid v1.4.0 github.com/google/uuid v1.4.0
github.com/gopxl/beep v1.4.1 github.com/gopxl/beep v1.4.1
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/hajimehoshi/oto v1.0.1
github.com/jackc/pgx/v5 v5.6.0 github.com/jackc/pgx/v5 v5.6.0
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.33.0 github.com/rs/zerolog v1.33.0
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
github.com/tosone/minimp3 v1.0.2
golang.org/x/crypto v0.21.0 golang.org/x/crypto v0.21.0
golang.org/x/term v0.18.0 golang.org/x/term v0.18.0
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.33.0
@ -25,10 +28,7 @@ require (
github.com/ajg/form v1.5.1 // indirect github.com/ajg/form v1.5.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/ebitengine/oto/v3 v3.1.0 // indirect
github.com/ebitengine/purego v0.7.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-json v0.10.2 // indirect
github.com/hajimehoshi/go-mp3 v0.3.4 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
@ -45,11 +45,13 @@ require (
github.com/lestrrat-go/option v1.0.1 // indirect github.com/lestrrat-go/option v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/asm v1.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/atomic v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect
golang.org/x/exp/shiny v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/image v0.14.0 // indirect
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a // indirect
golang.org/x/sync v0.5.0 // indirect golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.20.0 // indirect golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect

34
go.sum
View file

@ -24,10 +24,6 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/ebitengine/oto/v3 v3.1.0 h1:9tChG6rizyeR2w3vsygTTTVVJ9QMMyu00m2yBOCch6U=
github.com/ebitengine/oto/v3 v3.1.0/go.mod h1:IK1QTnlfZK2GIB6ziyECm433hAdTaPpOsGMLhEyEGTg=
github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE= github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw= github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
@ -53,9 +49,8 @@ github.com/gopxl/beep v1.4.1 h1:WqNs9RsDAhG9M3khMyc1FaVY50dTdxG/6S6a3qsUHqE=
github.com/gopxl/beep v1.4.1/go.mod h1:A1dmiUkuY8kxsvcNJNUBIEcchmiP6eUyCHSxpXl0YO0= github.com/gopxl/beep v1.4.1/go.mod h1:A1dmiUkuY8kxsvcNJNUBIEcchmiP6eUyCHSxpXl0YO0=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68= github.com/hajimehoshi/oto v1.0.1 h1:8AMnq0Yr2YmzaiqTg/k1Yzd6IygUGk2we9nmjgbgPn4=
github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo= github.com/hajimehoshi/oto v1.0.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos=
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -104,8 +99,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -129,17 +122,29 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tosone/minimp3 v1.0.2 h1:htFE2EbP7Y4CJ8KGW9c55tKWRpzv9kXkEmCYGxFzVjA=
github.com/tosone/minimp3 v1.0.2/go.mod h1:N6vjknGR7PboMTyJVhe/7RHNQiIc0jWZxFKlSWdfzwc=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/exp/shiny v0.0.0-20240719175910-8a7402abbf56 h1:8jM66xzUJjNInw31Y8bic4AYSLVChztDRT93+kmofUY=
golang.org/x/exp/shiny v0.0.0-20240719175910-8a7402abbf56/go.mod h1:3F+MieQB7dRYLTmnncoFbb1crS5lfQoTfDgQy6K4N0o=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a h1:sYbmY3FwUWCBTodZL1S3JUuOvaW6kM2o+clDzzDNBWg=
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a/go.mod h1:Ede7gF0KGoHlj822RtphAHK1jLdrcuRBZg0sF1Q+SPc=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -147,10 +152,11 @@ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=

View file

@ -1,107 +0,0 @@
// Package mp3 implements audio data decoding in MP3 format.
package mpg123
import (
"fmt"
"io"
"github.com/gopxl/beep"
"github.com/pkg/errors"
)
const (
gomp3NumChannels = 2
gomp3Precision = 2
gomp3BytesPerFrame = gomp3NumChannels * gomp3Precision
)
// Decode takes a ReadCloser containing audio data in MP3 format and returns a StreamSeekCloser,
// which streams that audio. The Seek method will panic if rc is not io.Seeker.
//
// Do not close the supplied ReadSeekCloser, instead, use the Close method of the returned
// StreamSeekCloser when you want to release the resources.
func Decode(rc io.ReadCloser) (s beep.StreamCloser, format beep.Format, err error) {
defer func() {
if err != nil {
err = errors.Wrap(err, "mp3")
}
}()
d, err := NewDecoder("")
if err != nil {
return nil, beep.Format{}, err
}
d.Format(8000, 2, ENC_FLOAT_64)
err = d.OpenFeed()
if err != nil {
return nil, beep.Format{}, err
}
// get 4k of file
buf := make([]byte, 4096)
for {
n, err := rc.Read(buf)
if err != nil && err != io.EOF {
return nil, beep.Format{}, err
}
if n == 0 {
break
}
err = d.Feed(buf)
if err != nil {
return nil, beep.Format{}, err
}
}
rate, channels, enc := d.GetFormat()
fmt.Printf("rate %d chan %d enc %d\n", rate, channels, enc)
format = beep.Format{
SampleRate: beep.SampleRate(8000),
NumChannels: 2,
Precision: 4,
}
return &decoder{rc, d, format, 0, nil}, format, nil
}
type decoder struct {
closer io.Closer
d *Decoder
f beep.Format
pos int
err error
}
func (d *decoder) Stream(samples [][2]float64) (n int, ok bool) {
if d.err != nil {
return 0, false
}
var tmp [gomp3BytesPerFrame]byte
for i := range samples {
dn, err := d.d.Read(tmp[:])
if dn == len(tmp) {
samples[i], _ = d.f.DecodeSigned(tmp[:])
d.pos += dn
n++
ok = true
}
if err == io.EOF {
break
}
if err != nil {
d.err = errors.Wrap(err, "mp3")
break
}
}
return n, ok
}
func (d *decoder) Err() error {
return d.err
}
func (d *decoder) Close() error {
err := d.closer.Close()
if err != nil {
return errors.Wrap(err, "mp3")
}
return d.d.Close()
}

View file

@ -1,189 +0,0 @@
// mpg123.go contains all bindings to the C library
package mpg123
/*
#include <stdlib.h>
#include <mpg123.h>
#cgo LDFLAGS: -lmpg123
int do_mpg123_read(mpg123_handle *mh, void *outmemory, size_t outmemsize, size_t *done) {
return mpg123_read(mh, outmemory, outmemsize, done);
}
*/
import "C"
import (
"errors"
"fmt"
"os"
"unsafe"
)
var EOF = errors.New("EOF")
// All output encoding formats supported by mpg123
const (
ENC_8 = C.MPG123_ENC_8
ENC_16 = C.MPG123_ENC_16
ENC_24 = C.MPG123_ENC_24
ENC_32 = C.MPG123_ENC_32
ENC_SIGNED = C.MPG123_ENC_SIGNED
ENC_FLOAT = C.MPG123_ENC_FLOAT
ENC_SIGNED_8 = C.MPG123_ENC_SIGNED_8
ENC_UNSIGNED_8 = C.MPG123_ENC_UNSIGNED_8
ENC_ULAW_8 = C.MPG123_ENC_ULAW_8
ENC_ALAW_8 = C.MPG123_ENC_ALAW_8
ENC_SIGNED_16 = C.MPG123_ENC_SIGNED_16
ENC_UNSIGNED_16 = C.MPG123_ENC_UNSIGNED_16
ENC_SIGNED_24 = C.MPG123_ENC_SIGNED_24
ENC_UNSIGNED_24 = C.MPG123_ENC_UNSIGNED_24
ENC_SIGNED_32 = C.MPG123_ENC_SIGNED_32
ENC_UNSIGNED_32 = C.MPG123_ENC_UNSIGNED_32
ENC_FLOAT_32 = C.MPG123_ENC_FLOAT_32
ENC_FLOAT_64 = C.MPG123_ENC_FLOAT_64
ENC_ANY = C.MPG123_ENC_ANY
)
// Contains a handle for and mpg123 decoder instance
type Decoder struct {
handle *C.mpg123_handle
}
// init initializes the mpg123 library when package is loaded
func init() {
err := C.mpg123_init()
if err != C.MPG123_OK {
//return fmt.Errorf("error initializing mpg123")
panic("failed to initialize mpg123")
}
//return nil
}
///////////////////////////
// DECODER INSTANCE CODE //
///////////////////////////
// NewDecoder creates a new mpg123 decoder instance
func NewDecoder(decoder string) (*Decoder, error) {
var err C.int
var mh *C.mpg123_handle
if decoder != "" {
mh = C.mpg123_new(nil, &err)
} else {
cdecoder := C.CString(decoder)
defer C.free(unsafe.Pointer(cdecoder))
mh = C.mpg123_new(cdecoder, &err)
}
if mh == nil {
errstring := C.mpg123_plain_strerror(err)
err := C.GoString(errstring)
C.free(unsafe.Pointer(errstring))
return nil, fmt.Errorf("error initializing mpg123 decoder: %s", err)
}
dec := new(Decoder)
dec.handle = mh
return dec, nil
}
// Delete frees an mpg123 decoder instance
func (d *Decoder) Delete() {
C.mpg123_delete(d.handle)
}
// returns a string containing the most recent error message corresponding to
// an mpg123 decoder instance
func (d *Decoder) strerror() string {
return C.GoString(C.mpg123_strerror(d.handle))
}
////////////////////////
// OUTPUT FORMAT CODE //
////////////////////////
// FormatNone disables all decoder output formats (used to specifying supported formats)
func (d *Decoder) FormatNone() {
C.mpg123_format_none(d.handle)
}
// FromatAll enables all decoder output formats (this is the default setting)
func (d *Decoder) FormatAll() {
C.mpg123_format_all(d.handle)
}
// GetFormat returns current output format
func (d *Decoder) GetFormat() (rate int64, channels int, encoding int) {
var cRate C.long
var cChans, cEnc C.int
C.mpg123_getformat(d.handle, &cRate, &cChans, &cEnc)
return int64(cRate), int(cChans), int(cEnc)
}
// Format sets the audio output format for decoder
func (d *Decoder) Format(rate int64, channels int, encodings int) {
C.mpg123_format(d.handle, C.long(rate), C.int(channels), C.int(encodings))
}
/////////////////////////////
// INPUT AND DECODING CODE //
/////////////////////////////
// Open initializes a decoder for an mp3 file using a filename
func (d *Decoder) Open(file string) error {
cfile := C.CString(file)
defer C.free(unsafe.Pointer(cfile))
err := C.mpg123_open(d.handle, cfile)
if err != C.MPG123_OK {
return fmt.Errorf("error opening %s: %s", file, d.strerror())
}
return nil
}
// OpenFile binds to an fd from an open *os.File for decoding
func (d *Decoder) OpenFile(f *os.File) error {
err := C.mpg123_open_fd(d.handle, C.int(f.Fd()))
if err != C.MPG123_OK {
return fmt.Errorf("error attaching file: %s", d.strerror())
}
return nil
}
// OpenFeed prepares a decoder for direct feeding via Feed(..)
func (d *Decoder) OpenFeed() error {
err := C.mpg123_open_feed(d.handle)
if err != C.MPG123_OK {
return fmt.Errorf("mpg123 error: %s", d.strerror())
}
return nil
}
// Close closes an input file if one was opened by mpg123
func (d *Decoder) Close() error {
err := C.mpg123_close(d.handle)
if err != C.MPG123_OK {
return fmt.Errorf("mpg123 error: %s", d.strerror())
}
return nil
}
// Read decodes data and into buf and returns number of bytes decoded.
func (d *Decoder) Read(buf []byte) (int, error) {
var done C.size_t
err := C.do_mpg123_read(d.handle, (unsafe.Pointer)(&buf[0]), C.size_t(len(buf)), &done)
if err == C.MPG123_DONE {
return int(done), EOF
}
if err != C.MPG123_OK {
return int(done), fmt.Errorf("mpg123 error: %s", d.strerror())
}
return int(done), nil
}
// Feed provides data bytes into the decoder
func (d *Decoder) Feed(buf []byte) error {
err := C.mpg123_feed(d.handle, (*C.uchar)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)))
if err != C.MPG123_OK {
return fmt.Errorf("mpg123 error: %s", d.strerror())
}
return nil
}