mirror of https://github.com/jetkvm/kvm.git
Fix audio quality and cleanup issues in audio implementation
- Fix OPUS_BANDWIDTH constant from 1104 to 1105 (fullband 20kHz vs superwideband 12kHz) - Fix PacketLossPerc default from 0 to 20 to match C layer default - Add early return in FEC recovery when pcm_frames <= 0 to avoid zero-frame ALSA writes - Remove unused InputRelay fields (source, ctx, cancel) and unused NewInputRelay parameter - Add async cleanup on timeout in SetAudioOutputEnabled/SetAudioInputEnabled
This commit is contained in:
parent
3d1c2a13b9
commit
d42024b024
4
audio.go
4
audio.go
|
|
@ -160,7 +160,7 @@ func startInputAudioUnderMutex(alsaPlaybackDevice string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
newSource := audio.NewCgoInputSource(alsaPlaybackDevice, getAudioConfig())
|
newSource := audio.NewCgoInputSource(alsaPlaybackDevice, getAudioConfig())
|
||||||
newRelay := audio.NewInputRelay(&newSource)
|
newRelay := audio.NewInputRelay()
|
||||||
|
|
||||||
if err := newRelay.Start(); err != nil {
|
if err := newRelay.Start(); err != nil {
|
||||||
audioLogger.Error().Err(err).Str("alsaPlaybackDevice", alsaPlaybackDevice).Msg("Failed to start input relay")
|
audioLogger.Error().Err(err).Str("alsaPlaybackDevice", alsaPlaybackDevice).Msg("Failed to start input relay")
|
||||||
|
|
@ -275,6 +275,7 @@ func SetAudioOutputEnabled(enabled bool) error {
|
||||||
case <-time.After(5 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
audioLogger.Error().Msg("Audio output start timed out after 5 seconds")
|
audioLogger.Error().Msg("Audio output start timed out after 5 seconds")
|
||||||
audioOutputEnabled.Store(false) // Revert state on timeout
|
audioOutputEnabled.Store(false) // Revert state on timeout
|
||||||
|
go stopOutputAudio() // Clean up any partial initialization asynchronously
|
||||||
return fmt.Errorf("audio output start timed out after 5 seconds")
|
return fmt.Errorf("audio output start timed out after 5 seconds")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -307,6 +308,7 @@ func SetAudioInputEnabled(enabled bool) error {
|
||||||
case <-time.After(5 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
audioLogger.Error().Msg("Audio input start timed out after 5 seconds")
|
audioLogger.Error().Msg("Audio input start timed out after 5 seconds")
|
||||||
audioInputEnabled.Store(false) // Revert state on timeout
|
audioInputEnabled.Store(false) // Revert state on timeout
|
||||||
|
go stopInputAudio() // Clean up any partial initialization asynchronously
|
||||||
return fmt.Errorf("audio input start timed out after 5 seconds")
|
return fmt.Errorf("audio input start timed out after 5 seconds")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ static uint16_t max_packet_size = 1500;
|
||||||
#define OPUS_VBR 1 // Variable bitrate mode enabled
|
#define OPUS_VBR 1 // Variable bitrate mode enabled
|
||||||
#define OPUS_VBR_CONSTRAINT 1 // Constrained VBR maintains bitrate ceiling
|
#define OPUS_VBR_CONSTRAINT 1 // Constrained VBR maintains bitrate ceiling
|
||||||
#define OPUS_SIGNAL_TYPE 3002 // OPUS_SIGNAL_MUSIC (optimized for music/audio content)
|
#define OPUS_SIGNAL_TYPE 3002 // OPUS_SIGNAL_MUSIC (optimized for music/audio content)
|
||||||
#define OPUS_BANDWIDTH 1104 // OPUS_BANDWIDTH_FULLBAND (0-20kHz frequency range)
|
#define OPUS_BANDWIDTH 1105 // OPUS_BANDWIDTH_FULLBAND (0-20kHz frequency range)
|
||||||
#define OPUS_LSB_DEPTH 16 // 16-bit PCM sample depth (S16_LE format)
|
#define OPUS_LSB_DEPTH 16 // 16-bit PCM sample depth (S16_LE format)
|
||||||
|
|
||||||
static uint8_t opus_dtx_enabled = 1;
|
static uint8_t opus_dtx_enabled = 1;
|
||||||
|
|
@ -1068,11 +1068,16 @@ __attribute__((hot)) int jetkvm_audio_decode_write(void * __restrict__ opus_buf,
|
||||||
fprintf(stdout, "INFO: playback: FEC recovered %d frames\n", pcm_frames);
|
fprintf(stdout, "INFO: playback: FEC recovered %d frames\n", pcm_frames);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "WARN: playback: FEC returned 0 frames (silence)\n");
|
pthread_mutex_unlock(&playback_mutex);
|
||||||
fflush(stderr);
|
return 0; // FEC returned no frames, nothing to write
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__builtin_expect(pcm_frames <= 0, 0)) {
|
||||||
|
pthread_mutex_unlock(&playback_mutex);
|
||||||
|
return 0; // Nothing to write
|
||||||
|
}
|
||||||
|
|
||||||
retry_write:
|
retry_write:
|
||||||
if (__builtin_expect(atomic_load(&playback_stop_requested), 0)) {
|
if (__builtin_expect(atomic_load(&playback_stop_requested), 0)) {
|
||||||
pthread_mutex_unlock(&playback_mutex);
|
pthread_mutex_unlock(&playback_mutex);
|
||||||
|
|
|
||||||
|
|
@ -142,21 +142,14 @@ func (r *OutputRelay) relayLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type InputRelay struct {
|
type InputRelay struct {
|
||||||
source *AudioSource
|
|
||||||
ctx context.Context
|
|
||||||
cancel context.CancelFunc
|
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
running atomic.Bool
|
running atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInputRelay(source *AudioSource) *InputRelay {
|
func NewInputRelay() *InputRelay {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
logger := logging.GetDefaultLogger().With().Str("component", "audio-input-relay").Logger()
|
logger := logging.GetDefaultLogger().With().Str("component", "audio-input-relay").Logger()
|
||||||
|
|
||||||
return &InputRelay{
|
return &InputRelay{
|
||||||
source: source,
|
|
||||||
ctx: ctx,
|
|
||||||
cancel: cancel,
|
|
||||||
logger: logger,
|
logger: logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -175,6 +168,5 @@ func (r *InputRelay) Stop() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cancel()
|
|
||||||
r.logger.Debug().Msg("input relay stopped")
|
r.logger.Debug().Msg("input relay stopped")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ func DefaultAudioConfig() AudioConfig {
|
||||||
BufferPeriods: 12,
|
BufferPeriods: 12,
|
||||||
DTXEnabled: true,
|
DTXEnabled: true,
|
||||||
FECEnabled: true,
|
FECEnabled: true,
|
||||||
PacketLossPerc: 0,
|
PacketLossPerc: 20,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue