fix: always use mono Opus encoder for voice transmission
Remove automatic stereo encoder selection based on buffer size. Voice transmission in the Mumble protocol uses mono Opus with the AppVoIP profile. The stereo encoder (AppAudio profile) is only appropriate for file playback, which is controlled by the explicit EnableStereoEncoder flag. Additionally, downmix stereo microphone input to mono before sending when no file playback is active. Previously, a stereo mic would cause the stereo encoder to be selected via the buffer-size heuristic, sending non-standard stereo Opus that could confuse other clients' decoders and cause distorted audio. This fixes 'user c has issues hearing audio from user a with distorted audio' when user a has a stereo-input USB headset or similar device.
This commit is contained in:
committed by
Brandon McGinty
parent
dfa184211e
commit
679127bcf1
@@ -53,12 +53,10 @@ type AudioStreamEvent struct {
|
||||
type AudioBuffer []int16
|
||||
|
||||
func (a AudioBuffer) writeAudio(client *Client, seq int64, final bool) error {
|
||||
// Choose encoder based on whether buffer size indicates stereo or mono
|
||||
// Always use the mono encoder for voice transmission. The stereo
|
||||
// encoder is only used when explicitly enabled for file playback.
|
||||
encoder := client.AudioEncoder
|
||||
frameSize := client.Config.AudioFrameSize()
|
||||
if len(a) == frameSize*AudioChannels && client.AudioEncoderStereo != nil {
|
||||
encoder = client.AudioEncoderStereo
|
||||
} else if client.IsStereoEncoderEnabled() && client.AudioEncoderStereo != nil {
|
||||
if client.IsStereoEncoderEnabled() && client.AudioEncoderStereo != nil {
|
||||
encoder = client.AudioEncoderStereo
|
||||
}
|
||||
if encoder == nil {
|
||||
|
||||
@@ -503,10 +503,21 @@ func (s *Stream) sourceRoutine(inputDevice *string) {
|
||||
recorder.RecordAudioFrame(recorderOutgoingSource, outputBuffer)
|
||||
}
|
||||
} else if hasMicInput {
|
||||
// Send mic when no file is playing
|
||||
outgoing <- gumble.AudioBuffer(int16Buffer)
|
||||
// Send mic when no file is playing. If the microphone is
|
||||
// stereo, downmix to mono since Mumble voice transmission
|
||||
// uses mono Opus encoding.
|
||||
outBuf := int16Buffer
|
||||
if s.sourceChannels == 2 {
|
||||
monoBuf := make([]int16, frameSize)
|
||||
for i := 0; i < frameSize; i++ {
|
||||
// Average left and right channels
|
||||
monoBuf[i] = int16((int32(int16Buffer[i*2]) + int32(int16Buffer[i*2+1])) / 2)
|
||||
}
|
||||
outBuf = monoBuf
|
||||
}
|
||||
outgoing <- gumble.AudioBuffer(outBuf)
|
||||
if recorder := s.getRecorder(); recorder != nil {
|
||||
recorder.RecordAudioFrame(recorderOutgoingSource, int16Buffer)
|
||||
recorder.RecordAudioFrame(recorderOutgoingSource, outBuf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user