diff --git a/.gitignore b/.gitignore index 16fad32..380ea08 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ dist *.prof *.out *.test -cert.pem \ No newline at end of file +cert.pem +*.gob \ No newline at end of file diff --git a/go.mod b/go.mod index 5e3e6db..001a44e 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,7 @@ module github.com/stieneee/mumble-discord-bridge go 1.15 require ( - github.com/bwmarrin/discordgo v0.23.2 - github.com/gorilla/websocket v1.4.2 // indirect + github.com/bwmarrin/discordgo v0.23.3-0.20210512035133-7d7206b01bb5 github.com/joho/godotenv v1.3.0 github.com/stieneee/gopus v0.0.0-20210424193312-6d10f6090335 github.com/stieneee/gumble v0.0.0-20210424210604-732f48b5e0de diff --git a/go.sum b/go.sum index 3a2be89..9eba3fd 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4= -github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= +github.com/bwmarrin/discordgo v0.23.3-0.20210512035133-7d7206b01bb5 h1:VtiZMSjY2N6XpM1luSchBVX76QURpS0HA7BffVuHOCo= +github.com/bwmarrin/discordgo v0.23.3-0.20210512035133-7d7206b01bb5/go.mod h1:OMKxbTmkKofBjBi4/yidO3ItxbJ6PUfEUkjchM4En8c= github.com/dchote/go-openal v0.0.0-20171116030048-f4a9a141d372 h1:tz3KnXWtRZR0RWOfcMNOw+HHezWLQa7vfSOWTtKjchI= github.com/dchote/go-openal v0.0.0-20171116030048-f4a9a141d372/go.mod h1:74z+CYu2/mx4N+mcIS/rsvfAxBPBV9uv8zRAnwyFkdI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -7,7 +7,6 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= diff --git a/internal/bridge/discord.go b/internal/bridge/discord.go index 9a46660..b68297b 100644 --- a/internal/bridge/discord.go +++ b/internal/bridge/discord.go @@ -14,9 +14,12 @@ import ( ) type fromDiscord struct { - decoder *gopus.Decoder - pcm chan []int16 - streaming bool + decoder *gopus.Decoder + pcm chan []int16 + receiving bool // is used to to track the assumption that we are streaming a continuos stream form discord + streaming bool // The buffer streaming is streaming out + lastSequence uint16 + lastTimeStamp uint32 } // DiscordDuplex Handle discord voice stream @@ -57,9 +60,6 @@ func (dd *DiscordDuplex) discordSendPCM(ctx context.Context, wg *sync.WaitGroup, // Generate Opus Silence Frame opusSilence := []byte{0xf8, 0xff, 0xfe} - for i := 3; i < frameSize; i++ { - opusSilence = append(opusSilence, 0x00) - } sleepTick := sleepct.SleepCT{} sleepTick.Start(20 * time.Millisecond) @@ -190,46 +190,79 @@ func (dd *DiscordDuplex) discordReceivePCM(ctx context.Context, wg *sync.WaitGro } dd.discordMutex.Lock() + _, ok = dd.fromDiscordMap[p.SSRC] - dd.discordMutex.Unlock() if !ok { newStream := fromDiscord{} newStream.pcm = make(chan []int16, 100) + newStream.receiving = false newStream.streaming = false - newStream.decoder, err = gopus.NewDecoder(48000, 1) + newStream.decoder, err = gopus.NewDecoder(48000, 1) // Decode into mono if err != nil { OnError("error creating opus decoder", err) + dd.discordMutex.Unlock() continue } - dd.discordMutex.Lock() + dd.fromDiscordMap[p.SSRC] = newStream - dd.discordMutex.Unlock() } - dd.discordMutex.Lock() - p.PCM, err = dd.fromDiscordMap[p.SSRC].decoder.Decode(p.Opus, 960, false) + s := dd.fromDiscordMap[p.SSRC] + + deltaT := int(p.Timestamp - s.lastTimeStamp) + if p.Sequence-s.lastSequence != 1 { + s.decoder.ResetState() + } + + // oldReceiving := s.receiving + + if !s.receiving || deltaT < 1 || deltaT > 960*25 { + // First packet assume deltaT + fmt.Println("replacing", deltaT, deltaT, 960) + deltaT = 960 + s.receiving = true + } + + s.lastTimeStamp = p.Timestamp + s.lastSequence = p.Sequence + + dd.fromDiscordMap[p.SSRC] = s dd.discordMutex.Unlock() + + p.PCM, err = s.decoder.Decode(p.Opus, deltaT*5, false) if err != nil { OnError("Error decoding opus data", err) continue } - if len(p.PCM) != 960 { - log.Println("Opus size error") - continue - } + // fmt.Println(p.SSRC, p.Type, deltaT, p.Sequence, p.Sequence-s.lastSequence, oldReceiving, s.streaming, len(p.Opus), len(p.PCM)) + + // Stereo to Mono - Testing + // if len(p.PCM) != 0 { + // mono := make([]int16, len(p.PCM)/2) + // x := 0 + // for i := 0; i < len(p.PCM); i = i + 2 { + // mono[x] = (p.PCM[i] / 2) + (p.PCM[i+1] / 2) + // x++ + // } + // p.PCM = mono[:] + // // fmt.Println("mono resample", len(p.PCM)) + // } else if len(p.PCM) == 0 { + // p.PCM = zeros[:] + // } + + // Push data into pcm channel in 10ms chunks of mono pcm data dd.discordMutex.Lock() - select { - case dd.fromDiscordMap[p.SSRC].pcm <- p.PCM[0:480]: - default: - log.Println("From Discord buffer full. Dropping packet") - dd.discordMutex.Unlock() - continue - } - select { - case dd.fromDiscordMap[p.SSRC].pcm <- p.PCM[480:960]: - default: - log.Println("From Discord buffer full. Dropping packet") + for l := 0; l < deltaT; l = l + 480 { + var next []int16 + u := l + 480 + next = p.PCM[l:u] + + select { + case dd.fromDiscordMap[p.SSRC].pcm <- next: + default: + log.Println("From Discord buffer full. Dropping packet") + } } dd.discordMutex.Unlock() } @@ -287,6 +320,7 @@ func (dd *DiscordDuplex) fromDiscordMixer(ctx context.Context, wg *sync.WaitGrou if dd.fromDiscordMap[i].streaming { x := dd.fromDiscordMap[i] x.streaming = false + x.receiving = false // toggle this here is not optimal but there is no better location atm. dd.fromDiscordMap[i] = x } } @@ -312,8 +346,8 @@ func (dd *DiscordDuplex) fromDiscordMixer(ctx context.Context, wg *sync.WaitGrou // Regular send mixed audio outBuf := make([]int16, 480) - for i := 0; i < len(outBuf); i++ { - for j := 0; j < len(internalMixerArr); j++ { + for j := 0; j < len(internalMixerArr); j++ { + for i := 0; i < len(internalMixerArr[j]); i++ { outBuf[i] += (internalMixerArr[j])[i] } }