Fix recording truncation and rate mismatch causing static
The recording pipeline had two bugs that combined to produce buzzing/static in recorded audio: 1. NormalizeStereoFrame truncated incoming audio frames to frameSize*AudioChannels samples. When the Opus decoder produced 20ms frames (1920 stereo samples) but the recorder used a 10ms frameSize (960 samples), half the audio from every packet was silently dropped. 2. The recorder's run() loop dequeued one fixed-length frame per source per tick. After truncation, the remaining 10ms of each 20ms packet was gone, so every other tick produced silence. This 50 Hz on/off pattern sounded like static. Fixes: - NormalizeStereoFrame no longer truncates; it only converts mono to stereo and preserves all audio data - RecordAudioFrame now accepts an explicit stereo flag from callers instead of guessing from sample count (which failed for even-length mono data like 480-sample mic frames) - run() accumulates variable-length frames per source and consumes them in fixed-size chunks, preserving any leftover for the next tick
This commit is contained in:
committed by
Brandon McGinty
parent
cd003d7ac4
commit
90f8a1ca5f
@@ -45,7 +45,7 @@ type FilePlayer interface {
|
||||
}
|
||||
|
||||
type Recorder interface {
|
||||
RecordAudioFrame(source uint32, samples []int16)
|
||||
RecordAudioFrame(source uint32, samples []int16, stereo bool)
|
||||
}
|
||||
|
||||
const recorderOutgoingSource uint32 = ^uint32(0)
|
||||
@@ -742,7 +742,7 @@ func (s *Stream) processAudioPacket(packet *gumble.AudioPacket, user *gumble.Use
|
||||
}
|
||||
}
|
||||
if recorder != nil && recordPtr > 0 {
|
||||
recorder.RecordAudioFrame(user.Session, recordBuffer[:recordPtr])
|
||||
recorder.RecordAudioFrame(user.Session, recordBuffer[:recordPtr], true)
|
||||
}
|
||||
|
||||
if len(emptyBufs) == 0 {
|
||||
@@ -932,7 +932,7 @@ func (s *Stream) sourceRoutine(inputDevice *string, stop chan bool, done chan st
|
||||
// Send stereo buffer when file is playing
|
||||
outgoing <- gumble.AudioBuffer(outputBuffer)
|
||||
if recorder := s.getRecorder(); recorder != nil {
|
||||
recorder.RecordAudioFrame(recorderOutgoingSource, outputBuffer)
|
||||
recorder.RecordAudioFrame(recorderOutgoingSource, outputBuffer, true)
|
||||
}
|
||||
} else if hasMicInput {
|
||||
// Send mic when no file is playing. If the microphone is
|
||||
@@ -949,7 +949,7 @@ func (s *Stream) sourceRoutine(inputDevice *string, stop chan bool, done chan st
|
||||
}
|
||||
outgoing <- gumble.AudioBuffer(outBuf)
|
||||
if recorder := s.getRecorder(); recorder != nil {
|
||||
recorder.RecordAudioFrame(recorderOutgoingSource, outBuf)
|
||||
recorder.RecordAudioFrame(recorderOutgoingSource, outBuf, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user