Add outgoing audio packet interval option

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-13 16:00:30 -04:00
committed by Brandon McGinty
parent 893908f9a1
commit d338925da6
3 changed files with 49 additions and 0 deletions
+14
View File
@@ -140,6 +140,20 @@ If you modify the config file while Barnard is running, your changes may be over
You can set username and defaultserver in your config file, and they will be used if none is specified when launching barnard. You can set username and defaultserver in your config file, and they will be used if none is specified when launching barnard.
(Note that the default username (an empty string) and the default server name (localhost:64738) have been the defaults for barnard up to this point, and have been left that way for compatibility.) (Note that the default username (an empty string) and the default server name (localhost:64738) have been the defaults for barnard up to this point, and have been left that way for compatibility.)
## Audio Packet Duration
Barnard sends 10 ms audio packets by default. On a slow or unstable connection,
using larger packets can reduce packet overhead and make short dropouts less
noticeable, at the cost of additional voice latency. Start Barnard with one of
the supported durations:
```sh
barnard --audio-interval 20
```
Supported values are `10`, `20`, `40`, and `60` milliseconds. Try `20` ms
first; use `40` ms only if the connection remains unreliable.
## Audio Devices ## Audio Devices
You can set the default input and output devices in the config file as well. You can set the default input and output devices in the config file as well.
+16
View File
@@ -70,6 +70,22 @@ func TestNotificationExpansionIsSinglePassAndNotifyDoesNotBlock(t *testing.T) {
} }
} }
func TestAudioIntervalDuration(t *testing.T) {
for _, milliseconds := range []int{10, 20, 40, 60} {
got, err := audioIntervalDuration(milliseconds)
if err != nil {
t.Errorf("audioIntervalDuration(%d): %v", milliseconds, err)
continue
}
if got != time.Duration(milliseconds)*time.Millisecond {
t.Errorf("audioIntervalDuration(%d) = %v", milliseconds, got)
}
}
if _, err := audioIntervalDuration(30); err == nil {
t.Fatal("audioIntervalDuration accepted unsupported duration")
}
}
func TestServerAddressDefaultsPortWithoutBreakingIPv6(t *testing.T) { func TestServerAddressDefaultsPortWithoutBreakingIPv6(t *testing.T) {
for input, want := range map[string]string{ for input, want := range map[string]string{
"server": "server:64738", "server": "server:64738",
+19
View File
@@ -11,6 +11,7 @@ import (
"net/http" "net/http"
"os" "os"
"strings" "strings"
"time"
barnlog "git.stormux.org/storm/barnard/log" barnlog "git.stormux.org/storm/barnard/log"
@@ -84,6 +85,7 @@ func main() {
configSet := false configSet := false
certificateSet := false certificateSet := false
buffers := flag.Int("buffers", 16, "number of audio buffers to use") buffers := flag.Int("buffers", 16, "number of audio buffers to use")
audioInterval := flag.Int("audio-interval", 10, "outgoing audio packet duration in ms (10, 20, 40, or 60)")
profile := flag.Bool("profile", false, "add http server to serve profiles") profile := flag.Bool("profile", false, "add http server to serve profiles")
noiseSuppressionEnabled := flag.Bool("noise-suppression", false, "enable noise suppression for microphone input") noiseSuppressionEnabled := flag.Bool("noise-suppression", false, "enable noise suppression for microphone input")
autoTransmit := flag.Bool("auto-transmit", false, "start transmitting immediately on connect") autoTransmit := flag.Bool("auto-transmit", false, "start transmitting immediately on connect")
@@ -94,6 +96,10 @@ func main() {
logFile := flag.String("logfile", "", "write logs to this file (logging is disabled when omitted)") logFile := flag.String("logfile", "", "write logs to this file (logging is disabled when omitted)")
flag.Parse() flag.Parse()
selectedAudioInterval, err := audioIntervalDuration(*audioInterval)
if err != nil {
handle_raw_error(err)
}
// Set up logging // Set up logging
var level barnlog.Level var level barnlog.Level
@@ -192,6 +198,7 @@ func main() {
NoiseSuppressor: noise.NewSuppressor(), NoiseSuppressor: noise.NewSuppressor(),
} }
b.Config.Buffers = *buffers b.Config.Buffers = *buffers
b.Config.AudioInterval = selectedAudioInterval
b.Config.DisableUDP = *tcpOnly b.Config.DisableUDP = *tcpOnly
b.Hotkeys = b.UserConfig.GetHotkeys() b.Hotkeys = b.UserConfig.GetHotkeys()
@@ -238,6 +245,18 @@ func main() {
handle_error(&b) handle_error(&b)
} }
// audioIntervalDuration converts the packet duration requested at startup to
// one of the Opus durations supported by Mumble.
func audioIntervalDuration(milliseconds int) (time.Duration, error) {
interval := time.Duration(milliseconds) * time.Millisecond
switch interval {
case 10 * time.Millisecond, 20 * time.Millisecond, 40 * time.Millisecond, 60 * time.Millisecond:
return interval, nil
default:
return 0, fmt.Errorf("audio interval must be 10, 20, 40, or 60 ms, got %d", milliseconds)
}
}
// serverAddress adds Mumble's default port without corrupting an IPv6 literal. // serverAddress adds Mumble's default port without corrupting an IPv6 literal.
func serverAddress(address string) string { func serverAddress(address string) string {
if _, port, err := net.SplitHostPort(address); err == nil && port != "" { if _, port, err := net.SplitHostPort(address); err == nil && port != "" {