sleepct and tests

This commit is contained in:
Tyler Stiene 2021-04-18 00:30:27 -04:00
parent bad460e57c
commit cc387ba3b9
8 changed files with 122 additions and 28 deletions

View File

@ -12,6 +12,12 @@ dev-race: $(GOFILES)
dev-profile: $(GOFILES)
goreleaser build --skip-validate --rm-dist && sudo ./dist/mumble-discord-bridge_linux_amd64/mumble-discord-bridge -cpuprofile cpu.prof
test-chart: SHELL:=/bin/bash
test-chart:
go test &
until pidof mumble-discord-bridge.test; do continue; done;
psrecord --plot test-cpu-memory.png $$(pidof mumble-discord-bridge.test)
docker-latest:
docker build -t stieneee/mumble-discord-bridge:latest .

View File

@ -61,7 +61,11 @@ func (dd *DiscordDuplex) discordSendPCM(ctx context.Context, wg *sync.WaitGroup,
opusSilence = append(opusSilence, 0x00)
}
ticker := NewTickerCT(20 * time.Millisecond)
// ticker := NewTickerCT(20 * time.Millisecond)
sleepTick := SleepCT{
d: 20 * time.Millisecond,
t: time.Now(),
}
lastReady := true
var readyTimeout *time.Timer
@ -97,7 +101,10 @@ func (dd *DiscordDuplex) discordSendPCM(ctx context.Context, wg *sync.WaitGroup,
return
default:
}
<-ticker.C
// <-ticker.C
sleepTick.SleepNextTarget()
if (len(pcm) > 1 && streaming) || (len(pcm) > dd.Bridge.BridgeConfig.DiscordStartStreamingCount && !streaming) {
if !streaming {
log.Println("Debug: Discord start speaking")
@ -134,7 +141,8 @@ func (dd *DiscordDuplex) discordSendPCM(ctx context.Context, wg *sync.WaitGroup,
// We want to do this after alerting the user of possible short speaking cycles
for i := 0; i < 5; i++ {
internalSend(opusSilence)
<-ticker.C
// <-ticker.C
sleepTick.SleepNextTarget()
}
dd.Bridge.DiscordVoice.Speaking(false)
@ -235,7 +243,10 @@ func (dd *DiscordDuplex) discordReceivePCM(ctx context.Context, wg *sync.WaitGro
}
func (dd *DiscordDuplex) fromDiscordMixer(ctx context.Context, wg *sync.WaitGroup, toMumble chan<- gumble.AudioBuffer) {
ticker := NewTickerCT(10 * time.Millisecond)
sleepTick := SleepCT{
d: 10 * time.Millisecond,
t: time.Now(),
}
sendAudio := false
wg.Add(1)
@ -244,9 +255,11 @@ func (dd *DiscordDuplex) fromDiscordMixer(ctx context.Context, wg *sync.WaitGrou
case <-ctx.Done():
wg.Done()
return
case <-ticker.C:
default:
}
sleepTick.SleepNextTarget()
dd.discordMutex.Lock()
sendAudio = false

BIN
docs/test-cpu-memory.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -44,7 +44,10 @@ func (m MumbleDuplex) OnAudioStream(e *gumble.AudioStreamEvent) {
}
func (m MumbleDuplex) fromMumbleMixer(ctx context.Context, wg *sync.WaitGroup, toDiscord chan []int16) {
ticker := NewTickerCT(10 * time.Millisecond)
sleepTick := SleepCT{
d: 10 * time.Millisecond,
t: time.Now(),
}
sendAudio := false
bufferWarning := false
@ -58,7 +61,7 @@ func (m MumbleDuplex) fromMumbleMixer(ctx context.Context, wg *sync.WaitGroup, t
default:
}
<-ticker.C
sleepTick.SleepNextTarget()
mutex.Lock()
@ -86,27 +89,28 @@ func (m MumbleDuplex) fromMumbleMixer(ctx context.Context, wg *sync.WaitGroup, t
mutex.Unlock()
outBuf := make([]int16, 480)
for i := 0; i < len(outBuf); i++ {
for j := 0; j < len(internalMixerArr); j++ {
outBuf[i] += (internalMixerArr[j])[i]
}
}
if len(toDiscord) > 20 {
if !bufferWarning {
log.Println("Warning: toDiscord buffer size")
bufferWarning = true
}
} else {
if bufferWarning {
log.Println("Resolved: toDiscord buffer size")
bufferWarning = false
}
}
if sendAudio {
outBuf := make([]int16, 480)
for i := 0; i < len(outBuf); i++ {
for j := 0; j < len(internalMixerArr); j++ {
outBuf[i] += (internalMixerArr[j])[i]
}
}
if len(toDiscord) > 20 {
if !bufferWarning {
log.Println("Warning: toDiscord buffer size")
bufferWarning = true
}
} else {
if bufferWarning {
log.Println("Resolved: toDiscord buffer size")
bufferWarning = false
}
}
select {
case toDiscord <- outBuf:
default:

41
sleepct.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"fmt"
"sync"
"time"
)
// SleepCT - Sleep constant time step crates a sleep based ticker
// designed maintain a sleep/tick interval
type SleepCT struct {
sync.Mutex
d time.Duration // duration
t time.Time // last time target
}
func (s *SleepCT) SleepNextTarget() {
s.Lock()
now := time.Now()
var last time.Time
if s.t.IsZero() {
fmt.Println("SleepCT reset")
last = now.Add(-s.d)
} else {
last = s.t
}
// Next Target
s.t = last.Add(s.d)
d := s.t.Sub(now)
time.Sleep(d)
// delta := now.Sub(s.t)
// fmt.Println("delta", delta, d, time.Since(s.t))
s.Unlock()
}

BIN
test-cpu-memory.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -7,7 +7,7 @@ import (
"time"
)
// A Ticker holds a channel that delivers ``ticks'' of a clock
// A Ticker holds a channel that delivers ``ticks'' of a clockinter
// at intervals.
type TickerCT struct {
sync.Mutex

View File

@ -70,3 +70,33 @@ func TestTickerCT(t *testing.T) {
wg.Wait()
}
func testSleepCT(wg *sync.WaitGroup) {
wg.Add(1)
go func(interval time.Duration) {
now := time.Now()
start := now
// start the ticker
s := SleepCT{
d: interval,
t: time.Now(),
}
var i int64
for i = 0; i < testCount; i++ {
if i+1 < testCount {
time.Sleep(time.Duration(float64(maxSleepInterval) * rand.Float64()))
}
s.SleepNextTarget()
}
fmt.Println("SleepCT after", testDuration, "drifts", time.Since(start)-testDuration)
wg.Done()
}(tickerInterval)
}
func TestSleepCT(t *testing.T) {
wg := sync.WaitGroup{}
testSleepCT(&wg)
wg.Wait()
}