mirror of https://github.com/jetkvm/kvm.git
Enable ALSA rate resampling for configurable audio sample rates
Changes the audio subsystem from hw: (direct hardware access) to plughw: (plugin layer with rate conversion) to enable configurable sample rates. Changes: - Update ALSA build to include plug,rate,linear,copy plugins - Change device names from hw: to plughw: in C and Go code - Remove 48kHz hardcoding for HDMI audio output - Keep USB at 48kHz since hardware is fixed at that rate - Update all comments to reflect plughw usage Technical details: - hw: devices bypass all ALSA plugins and require exact hardware rate match - plughw: devices enable the ALSA plugin layer for automatic rate conversion - Hardware still receives at native rate (48kHz), resampling happens in userspace - HDMI can now use 8k/12k/16k/24k/48kHz, USB remains at 48kHz - NEON-optimized resampling provides good performance on Cortex-A7 Requires rebuilding ALSA library with updated plugin configuration.
This commit is contained in:
parent
2040db6094
commit
0be9dbcc6c
|
|
@ -48,7 +48,7 @@ if [ ! -f .built ]; then
|
|||
# Use minimal ALSA configuration to avoid FD_SETSIZE issues in devcontainer
|
||||
CFLAGS="$OPTIM_CFLAGS" ./configure --host $BUILDKIT_FLAVOR \
|
||||
--enable-static=yes --enable-shared=no \
|
||||
--with-pcm-plugins=rate,linear \
|
||||
--with-pcm-plugins=plug,rate,linear,copy \
|
||||
--disable-seq --disable-rawmidi --disable-ucm \
|
||||
--disable-python --disable-old-symbols \
|
||||
--disable-topology --disable-hwdep --disable-mixer \
|
||||
|
|
|
|||
4
audio.go
4
audio.go
|
|
@ -30,9 +30,9 @@ var (
|
|||
|
||||
func getAlsaDevice(source string) string {
|
||||
if source == "hdmi" {
|
||||
return "hw:0,0"
|
||||
return "plughw:0,0"
|
||||
}
|
||||
return "hw:1,0"
|
||||
return "plughw:1,0"
|
||||
}
|
||||
|
||||
func initAudio() {
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
*
|
||||
* Bidirectional audio processing optimized for ARM NEON SIMD:
|
||||
* - OUTPUT PATH: TC358743 HDMI or USB Gadget audio → Client speakers
|
||||
* Pipeline: ALSA hw:0,0 or hw:1,0 capture → Opus encode (192kbps, FEC enabled)
|
||||
* Pipeline: ALSA plughw:0,0 or plughw:1,0 capture → Opus encode (192kbps, FEC enabled)
|
||||
*
|
||||
* - INPUT PATH: Client microphone → Device speakers
|
||||
* Pipeline: Opus decode (with FEC) → ALSA hw:1,0 playback
|
||||
* Pipeline: Opus decode (with FEC) → ALSA plughw:1,0 playback
|
||||
*
|
||||
* Key features:
|
||||
* - ARM NEON SIMD optimization for all audio operations
|
||||
* - Opus in-band FEC for packet loss resilience
|
||||
* - S16_LE stereo, 20ms frames (sample rate configurable: 8k/12k/16k/24k/48kHz)
|
||||
* - ALSA rate plugin resamples hardware output to match requested Opus-compatible rate
|
||||
* - ALSA plughw layer provides automatic rate conversion from hardware to Opus rate
|
||||
*/
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
|
@ -140,19 +140,19 @@ void update_audio_decoder_constants(uint32_t sr, uint8_t ch, uint16_t fs, uint16
|
|||
* Must be called before jetkvm_audio_capture_init or jetkvm_audio_playback_init
|
||||
*
|
||||
* Device mapping (set via ALSA_CAPTURE_DEVICE/ALSA_PLAYBACK_DEVICE):
|
||||
* hw:0,0 = TC358743 HDMI audio input (for OUTPUT path capture)
|
||||
* hw:1,0 = USB Audio Gadget (for OUTPUT path capture or INPUT path playback)
|
||||
* plughw:0,0 = TC358743 HDMI audio with rate conversion (for OUTPUT path capture)
|
||||
* plughw:1,0 = USB Audio Gadget with rate conversion (for OUTPUT path capture or INPUT path playback)
|
||||
*/
|
||||
static void init_alsa_devices_from_env(void) {
|
||||
// Always read from environment to support device switching
|
||||
alsa_capture_device = getenv("ALSA_CAPTURE_DEVICE");
|
||||
if (alsa_capture_device == NULL || alsa_capture_device[0] == '\0') {
|
||||
alsa_capture_device = "hw:1,0"; // Default: USB gadget audio for capture
|
||||
alsa_capture_device = "plughw:1,0"; // Default: USB gadget audio for capture with rate conversion
|
||||
}
|
||||
|
||||
alsa_playback_device = getenv("ALSA_PLAYBACK_DEVICE");
|
||||
if (alsa_playback_device == NULL || alsa_playback_device[0] == '\0') {
|
||||
alsa_playback_device = "hw:1,0"; // Default: USB gadget audio for playback
|
||||
alsa_playback_device = "plughw:1,0"; // Default: USB gadget audio for playback with rate conversion
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -430,7 +430,7 @@ static int configure_alsa_device(snd_pcm_t *handle, const char *device_name, uin
|
|||
|
||||
/**
|
||||
* Initialize OUTPUT path (HDMI or USB Gadget audio capture → Opus encoder)
|
||||
* Opens ALSA capture device from ALSA_CAPTURE_DEVICE env (default: hw:1,0, set to hw:0,0 for TC358743 HDMI)
|
||||
* Opens ALSA capture device from ALSA_CAPTURE_DEVICE env (default: plughw:1,0, set to plughw:0,0 for HDMI)
|
||||
* and creates Opus encoder with optimized settings
|
||||
* @return 0 on success, -EBUSY if initializing, -1/-2/-3 on errors
|
||||
*/
|
||||
|
|
@ -606,7 +606,7 @@ retry_read:
|
|||
|
||||
/**
|
||||
* Initialize INPUT path (Opus decoder → device speakers)
|
||||
* Opens ALSA playback device from ALSA_PLAYBACK_DEVICE env (default: hw:1,0)
|
||||
* Opens ALSA playback device from ALSA_PLAYBACK_DEVICE env (default: plughw:1,0)
|
||||
* and creates Opus decoder. Returns immediately on device open failure (no fallback).
|
||||
* @return 0 on success, -EBUSY if initializing, -1/-2 on errors
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -83,10 +83,13 @@ func (c *CgoSource) Connect() error {
|
|||
func (c *CgoSource) connectOutput() error {
|
||||
os.Setenv("ALSA_CAPTURE_DEVICE", c.alsaDevice)
|
||||
|
||||
// USB Audio Gadget (hw:1,0) only supports 48kHz
|
||||
// For HDMI (hw:0,0), use configured sample rate
|
||||
// Using plughw: enables ALSA rate conversion plugin
|
||||
// USB Gadget hardware is fixed at 48kHz (configfs hardcoded), so keep it at 48kHz
|
||||
// HDMI can use configured rate - plughw resamples from hardware rate to Opus rate
|
||||
sampleRate := c.config.SampleRate
|
||||
if c.alsaDevice == "hw:1,0" {
|
||||
if c.alsaDevice == "plughw:1,0" {
|
||||
sampleRate = 48000
|
||||
} else if sampleRate == 0 {
|
||||
sampleRate = 48000
|
||||
}
|
||||
frameSize := uint16(sampleRate * 20 / 1000)
|
||||
|
|
|
|||
Loading…
Reference in New Issue