[Image: banniereforumhifi.jpg] (September 11) x

Note de ce sujet :
  • Moyenne : 5 (1 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Installation de HQPe/NAA/Diretta ALSA drivers sous Fedora
#21
(09-11-2024, 04:03 PM)zaurux a écrit : Il m'a gentiment renvoyé vers GentooPlayer et me dit qu'il faut avoir les sources pour compiler sous Arch.
Là je suis d'accord mais je ne sais ù les trouver.
Une piste ?

Et excuse moi pour le HS Fedora  Envers

Bonjour Stéphane,

Yu a publié sur son site Preview des liens de téléchargement automatiques vers les dernières versions.


(09-11-2024, 09:00 PM)Le dom a écrit : Si tu veux partir sur une distribution ArchLinux, je te conseille Audiolinux beaucoup plus abouti que ArchQ. De plus Audiolinux supporte Diretta.

Bonjour Le Dom,

As-tu essayé ArchQ ?

Certes Audiolinux est une bonne distro, mais elle est payante.

Du coup, ArchQ vaut peut-être le coup d'être testé tu ne penses pas ?

Concernant la compilation des drivers Diretta est assez simple, du moment que l'on dispose des outils nécessaires, et en particulier de la copie du noyau.
Répondre
#22
J’ai regardé vite fait et j’ai l’impression que l’on ne peut pas y installer ce que l’on veut.
J’y jetterai un coup d’œil à l’occasion pour voir ce que l’on peut faire avec.
Source: PC CPU AMD Ryzen 9 5900X Audiolinux  v3 7.00 - Alim JCAT OPTIMO S ATX + Target Diretta Ustars C19 avec AL RPI 4.40 + Clock by FLR - alim DIY 4 x 5V avec transfos Toroïdy Audio Grade Supreme et composants Audio Grade pour C19, clock FLR, carte JCAT Net Card XE.
DAC: Holo Audio Spring 3 Level 2 - Ampli intégré: La Rosita Maverick -Switches RJ45: Reddo Audio + HNE MagicNet D1 Supreme - Enceintes: AudioPhysic Cardeas - Câblage: vers full Murmure Audio.
Répondre
#23
Une autre distro ArchLinux me semble digne d'intérêt: CachyOS Linux.
Ils annoncent en effet des noyaux optimisés autour du micro-code des version X86-v3, X86-v4 et même Zen4: https://cachyos.org/blog/2407-july-release/
Ils cherchent à optimiser le scheduler ainsi qu'à réduire la latence.
Cela me parait une alternative plus ouverte et en tous cas assez efficace au plan de l'optimisation du noyau.
Elle a été benchmarkée par Phoronix: https://www.phoronix.com/review/cachyos-x86-64-v3-v4

Concernant ArchQ, j'ai un doute sur la validité du claim du développeur concernant l'optimisation du noyau à 352kHz qui éviterait l'upsampling... Mais je trouve cela amusant et lorsque j'aurai un peu de temps, je testerai...
Répondre
#24
En fait Audiolinux 6.10 v3 et v4 sont basés sur une structure CachyOS.
Source: PC CPU AMD Ryzen 9 5900X Audiolinux  v3 7.00 - Alim JCAT OPTIMO S ATX + Target Diretta Ustars C19 avec AL RPI 4.40 + Clock by FLR - alim DIY 4 x 5V avec transfos Toroïdy Audio Grade Supreme et composants Audio Grade pour C19, clock FLR, carte JCAT Net Card XE.
DAC: Holo Audio Spring 3 Level 2 - Ampli intégré: La Rosita Maverick -Switches RJ45: Reddo Audio + HNE MagicNet D1 Supreme - Enceintes: AudioPhysic Cardeas - Câblage: vers full Murmure Audio.
Répondre
#25
Merci pour cette précision. Cela fait du sens et permet de mieux comprendre l'enthousiasme partagé autour de ces nouvelles architectures de processeurs Wink
Répondre
#26
Je vous donne la réponse "in extenso" du développeur d'ArchQ qui est assez réactif (via GitHub).

Citation :This is Diretta box driver(alsa_bridge.ko) for ArchQ Q441 kernel.
You can download the file and auto extract it as below command.

modéré

to install the driver.
Hope this driver works well.
! Mon installation !
ROON + HQP / Hdplex H3-i5 > DST-00 Diretta > HOLO Spring 3 > SQM > Benchmark AHB2 / Wilson Benesch Square5
Répondre
#27
Mea culpa, maxima culpa... et la démarche était purement personne.. à usage personnel.
J'aurai juste du m'en ternir à des échanges privés sans les partager.
A noter, que cette distribution même si elle apparait incomplète n'a aucune velléité commerciale et respecte totalement le texte de YU, cité ci-dessus.
Dans tous les cas, il convient de ne pas polluer le fil de Bear.
! Mon installation !
ROON + HQP / Hdplex H3-i5 > DST-00 Diretta > HOLO Spring 3 > SQM > Benchmark AHB2 / Wilson Benesch Square5
Répondre
#28
Bonjour,

Les distros d'Audio-Linux et de GentooPlayer offrent des noyaux 'customisés' qui sont en général facturés séparément, et renchérissent le montant de l'abonnement.

Il est maintenant assez facile d'optimiser son propre noyau lors de la compilation.
Un user-guide facile à suivre pour Fedora se trouve ici: https://linuxconfig.org/how-to-compile-v...-on-fedora

Les sources de la dernière version du noyau sont ici: https://git.kernel.org/pub/scm/linux/ker...linux.git/
On peut facilement spécifier dans la phase "make menuconfig" que l'on souhaite un noyau temps réel.

Enfin, si l'on souhaite encore affiner, on peut s'appuyer sur les moteurs d'IA pour nous aider.
J'ai ainsi trouvé sur Grok, le moteur concurrent de ChatGPT, le tuto suivant pour optimiser pour un processeur Zen 4 d'AMD.

To optimize the Linux kernel for the AMD Zen 4 architecture in Linux kernel version 6.12, you can follow these steps:

1. **Kernel Configuration:**

  - **Use Custom Compilation:**
    When compiling the kernel, you need to set specific compiler flags that target the Zen 4 architecture. This can be done by modifying the kernel's make configuration:

    ```bash
    make menuconfig
    ```

    Navigate to:
    - **Processor type and features**
      - Here, you might not find an explicit option for Zen 4 (znver4) in older or standard kernel configurations, but you can manually set the architecture for compilation:

    - **Advanced options**
      - **Kernel .config support**
        - Set `CONFIG_MZEN4=y` if available. This would typically enable optimizations for the Zen 4 architecture.

  - **If `CONFIG_MZEN4` is not available:**
    You might need to edit the `.config` file directly or add it to the `Kconfig` if you're customizing the kernel setup. However, for Zen 4, you would usually use:
   
    ```bash
    echo "CONFIG_MARCH_ZNVER4=y" >> .config
    ```

    Or ensure your make command includes these flags:

    ```bash
    make -j $(nproc) KCFLAGS="-march=znver4 -mtune=znver4" LOCALVERSION=-zn4
    ```

2. **Compiler Optimization:**

  - When building the kernel or any other software for Zen 4, ensure your GCC compiler supports the `-march=znver4` flag. This flag tells the compiler to generate code specifically optimized for Zen 4.

  - Check your GCC version for support:
    ```bash
    gcc --target-help | grep znver4
    ```

  - If supported, use:
    ```bash
    export CFLAGS="-march=znver4 -mtune=znver4 -O2 -pipe"
    ```

  This should be added to your environment or included in the kernel's build process.

3. **Microcode Update:**

  - Ensure your system's microcode is up-to-date for Zen 4. Although this doesn't directly involve the kernel compilation, having the latest microcode can provide better performance and stability.

  - Check for microcode updates in your distribution or manually update via `iucode-tool`.

4. **Performance Monitoring:**
  - Utilize perf tools optimized for Zen 4. Linux 6.2 and later versions include enhanced perf counters for AMD Zen 4, which can help in identifying performance bottlenecks.

5. **Documentation and Patches:**
  - Review the Linux kernel documentation and any patches specific to Zen 4 optimizations, as these might include tweaks or new features beneficial for your hardware.

6. **Community Resources:**
  - Check online forums like Reddit's r/archlinux, Linux Mint forums, or other Linux communities where users might share custom patches or configurations for Ryzen CPUs.

Remember, while these steps can help optimize for Zen 4, the performance gains might be marginal in day-to-day use unless you're running very specific workloads that benefit from the architecture's enhancements. Also, ensure you have backups before experimenting with custom kernel builds, as incorrect configurations can lead to system instability.

Voilà. Plutôt cool de se compiler son propre noyau et de l'installer sur son serveur Cool
Répondre
#29
Je ré-ouvre ce sujet par un script de compilation du noyau en version RT.
J'ai écrit ce script avec l'aide de l'IA pour me permettre de suivre les nouvelles versions de noyau qui sont publiées par Linus Torvald toutes les semaines.

Il suffit de télécharger le noyau ici: https://git.kernel.org/pub/scm/linux/ker...linux.git/

de le décompresser (tar -xvf ...), de copier le fichier de configuration de sa machine vers le répertoire créé, d'y copier le script ci-dessous après l'avoir rendu exécutable, et de le faire tourner.

Ce script sélectionne par défaut les options RT (PREEMP_RT) et rajoute une fréquence à 2000 Hz pour le scheduler.

Sous toutes réserves. Enjoy Wink

Code :
#!/bin/bash
set -e

# ============================================
# CHECK DEPENDENCIES
# ============================================

echo "=== Checking build dependencies ==="

REQUIRED_TOOLS=(
    "make"
    "gcc"
    "bc"
    "bison"
    "flex"
    "libelf-dev"
    "libssl-dev"
    "rpm-build"
    "ncurses-dev"
)

MISSING_DEPS=()

for tool in "${REQUIRED_TOOLS[@]}"; do
    # Check if package-based tool
    if [[ "$tool" == *-dev ]]; then
        # For .deb systems (convert to package name check)
        pkg_name="${tool%-dev}"
        if ! dpkg -l | grep -qw "$pkg_name" 2>/dev/null; then
            MISSING_DEPS+=("$tool")
        fi
    else
        # Check if command exists
        if ! command -v "$tool" &> /dev/null; then
            MISSING_DEPS+=("$tool")
        fi
    fi
done

if [ ${#MISSING_DEPS[@]} -gt 0 ]; then
    echo "✗ Missing dependencies:"
    printf '  - %s\n' "${MISSING_DEPS[@]}"
    echo ""
    echo "Install with:"
    echo "  sudo dnf install gcc make bc bison flex elfutils-libelf-devel openssl-devel rpm-build ncurses-devel"
    exit 1
fi

echo "✓ All dependencies satisfied"
echo ""


echo "=== Audio-Optimized RT Kernel Build Script ==="
echo ""

# ============================================
# DETECT CPU ARCHITECTURE
# ============================================

echo "=== Detecting CPU Architecture ==="

CPU_VENDOR=$(lscpu | grep "Vendor ID" | awk '{print $3}')
CPU_MODEL=$(lscpu | grep "Model name" | cut -d: -f2 | xargs)
CPU_FAMILY=$(lscpu | grep "CPU family" | awk '{print $3}')
CPU_MODEL_NUM=$(lscpu | grep -w "Model:" | awk '{print $2}')

echo "CPU Vendor: $CPU_VENDOR"
echo "CPU Model: $CPU_MODEL"
echo "CPU Family: $CPU_FAMILY"
echo "CPU Model Number: $CPU_MODEL_NUM"

# Detect Zen4 (Family 25, Model >= 96)
# Zen4: Ryzen 7000 series, EPYC 9004 series
IS_ZEN4=false

if [ "$CPU_VENDOR" = "AuthenticAMD" ]; then
    if [ "$CPU_FAMILY" = "25" ] && [ "$CPU_MODEL_NUM" -ge 96 ]; then
        IS_ZEN4=true
    elif echo "$CPU_MODEL" | grep -Eq "Ryzen.*(7[0-9]{3}|9[0-9]{3})"; then
        IS_ZEN4=true
    elif echo "$CPU_MODEL" | grep -Eq "EPYC.*9[0-9]{3}"; then
        IS_ZEN4=true
    fi
fi

if [ "$IS_ZEN4" = true ]; then
    echo ""
    echo "✓ Zen4 architecture detected!"
    echo "  Enabling optimizations: -march=x86-64-v4 -mtune=znver4 -O3"
    KCFLAGS="-march=x86-64-v4 -mtune=znver4 -O3"
else
    echo ""
    echo "→ Non-Zen4 CPU detected"
    echo "  Using standard compilation flags"
    KCFLAGS=""
fi

echo ""

# ============================================
# CLEAN BUILD ENVIRONMENT
# ============================================

echo "=== Cleaning build environment ==="
make mrproper

# ============================================
# PATCH 1: kernel/Kconfig.hz for HZ_2000
# ============================================

echo "=== Patching Kconfig.hz for HZ_2000 ==="

KCONFIG_HZ="kernel/Kconfig.hz"

if [ ! -f "$KCONFIG_HZ" ]; then
    echo "✗ Error: $KCONFIG_HZ not found"
    echo "Are you in the kernel source directory?"
    exit 1
fi

if grep -q "config HZ_2000" "$KCONFIG_HZ"; then
    echo "✓ HZ_2000 already present"
else
    echo "⚠ Adding HZ_2000 support..."
   
    cp "$KCONFIG_HZ" "${KCONFIG_HZ}.backup"
   
    # Insert HZ_2000 config option after HZ_1000
    awk '
    /config HZ_1000/ { in_hz1000=1 }
    in_hz1000 && /^$/ && !hz2000_added {
        print "\tconfig HZ_2000"
        print "\t\tbool \"2000 HZ\""
        print "\thelp"
        print "\t 2000 Hz is suited for audio production and low-latency applications."
        print ""
        hz2000_added=1
    }
    { print }
    ' "${KCONFIG_HZ}.backup" > "$KCONFIG_HZ.tmp"
   
    # Add default 2000 case
    awk '
    /^config HZ$/ { in_hz_section=1 }
    in_hz_section && /default 1000 if HZ_1000/ {
        print
        print "\tdefault 2000 if HZ_2000"
        next
    }
    { print }
    ' "$KCONFIG_HZ.tmp" > "$KCONFIG_HZ"
   
    rm "$KCONFIG_HZ.tmp"
    echo "✓ HZ_2000 patch applied"
fi

echo ""

# ============================================
# PATCH 2: ATO_BITS in inet_connection_sock.h
# ============================================

echo "=== Patching ATO_BITS for better network performance ==="

INET_SOCK_H="include/net/inet_connection_sock.h"

if [ ! -f "$INET_SOCK_H" ]; then
    echo "✗ Error: $INET_SOCK_H not found"
    exit 1
fi

# Check current ATO_BITS value (more robust check)
CURRENT_ATO_LINE=$(grep -n "#define[[:space:]]*ATO_BITS" "$INET_SOCK_H" 2>/dev/null | head -1)

if [ -z "$CURRENT_ATO_LINE" ]; then
    echo "✗ Error: ATO_BITS definition not found in $INET_SOCK_H"
    echo "File may have changed. Manual inspection required."
    exit 1
fi

CURRENT_ATO_VALUE=$(echo "$CURRENT_ATO_LINE" | awk '{print $NF}')

if [ "$CURRENT_ATO_VALUE" = "10" ]; then
    echo "✓ ATO_BITS already set to 10"
elif [ "$CURRENT_ATO_VALUE" = "8" ]; then
    echo "⚠ Changing ATO_BITS from 8 to 10..."
   
    # Backup
    cp "$INET_SOCK_H" "${INET_SOCK_H}.backup"
   
    # Change ATO_BITS 8 to 10
    sed -i 's/\(#define[[:space:]]*ATO_BITS[[:space:]]*\)8/\110/' "$INET_SOCK_H"
   
    # Verify change
    NEW_ATO=$(grep "#define[[:space:]]*ATO_BITS" "$INET_SOCK_H" | awk '{print $NF}')
   
    if [ "$NEW_ATO" = "10" ]; then
        echo "✓ Changed: #define ATO_BITS 10"
    else
        echo "✗ Patch failed! Restoring backup..."
        mv "${INET_SOCK_H}.backup" "$INET_SOCK_H"
        exit 1
    fi
else
    echo "⚠ Warning: ATO_BITS is $CURRENT_ATO_VALUE (expected 8 or 10)"
    read -p "Continue anyway? [y/N] " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        exit 1
    fi
fi

echo ""

# ============================================
# Generate base config from loaded modules
# ============================================

echo "=== Generating localmodconfig ==="
make localmodconfig

# Backup config AFTER localmodconfig
echo "=== Backing up config ==="
cp .config .config.backup

# ============================================
# Apply optimizations
# ============================================

echo ""
echo "=== Configuring Audio-Optimized RT Kernel ==="

# CRITICAL: Remove debug symbols
scripts/config --enable DEBUG_INFO_NONE
scripts/config --disable DEBUG_INFO_DWARF5
scripts/config --disable DEBUG_INFO_BTF
scripts/config --disable DEBUG_INFO_BTF_MODULES
scripts/config --disable GDB_SCRIPTS

# Size reduction
scripts/config --disable MAXSMP
scripts/config --set-val NR_CPUS 24
scripts/config --disable SECURITY_SELINUX
scripts/config --disable SECURITY_APPARMOR
scripts/config --disable IMA
scripts/config --disable AUDIT
scripts/config --disable FTRACE
scripts/config --disable KVM

# RT settings (CRITICAL for audio)
scripts/config --enable PREEMPT_RT
scripts/config --enable HZ_2000
scripts/config --enable HIGH_RES_TIMERS
scripts/config --enable NO_HZ_FULL
scripts/config --enable RCU_BOOST

# Network optimizations
scripts/config --enable TCP_CONG_BBR
scripts/config --set-str DEFAULT_TCP_CONG "bbr"

# ============================================
# CIFS/SMB SUPPORT - ADDED
# ============================================

echo ""
echo "=== Enabling CIFS/SMB Support ==="

# Core CIFS module
scripts/config --module CIFS

# Essential CIFS features
scripts/config --enable CIFS_ALLOW_INSECURE_LEGACY  # SMB1 support (if needed)
scripts/config --enable CIFS_WEAK_PW_HASH          # Legacy password hashing
scripts/config --enable CIFS_UPCALL                # Kerberos/SPNEGO support
scripts/config --enable CIFS_XATTR                  # Extended attributes
scripts/config --enable CIFS_POSIX                  # POSIX extensions
scripts/config --enable CIFS_DEBUG                  # Debug support
scripts/config --enable CIFS_DEBUG2                # Additional debugging
scripts/config --enable CIFS_DFS_UPCALL            # DFS support

# Optional features (comment out if not needed)
# scripts/config --enable CIFS_SMB_DIRECT          # RDMA support (needs INFINIBAND)
# scripts/config --enable CIFS_FSCACHE              # FS-Cache support

# Required crypto dependencies (should already be enabled)
scripts/config --enable CRYPTO_MD5
scripts/config --enable CRYPTO_SHA256
scripts/config --enable CRYPTO_SHA512
scripts/config --enable CRYPTO_AES
scripts/config --enable CRYPTO_CMAC
scripts/config --enable CRYPTO_ECB
scripts/config --enable CRYPTO_HMAC

echo "✓ CIFS configuration applied"

# Update config with all changes
make olddefconfig

# ============================================
# Verify critical settings
# ============================================

echo ""
echo "=== Verifying Configuration ==="

check_config() {
    local option=$1
    local expected=$2
    local actual=$(grep "^CONFIG_${option}=" .config 2>/dev/null | cut -d= -f2)
   
    if [ -z "$actual" ]; then
        actual=$(grep "^# CONFIG_${option} is not set" .config 2>/dev/null)
        if [ -n "$actual" ] && [ "$expected" = "n" ]; then
            echo "✓ CONFIG_${option} is not set (as expected)"
            return 0
        fi
        echo "⚠ CONFIG_${option} not set"
        return 1
    elif [ "$actual" = "$expected" ]; then
        echo "✓ CONFIG_${option}=${actual}"
        return 0
    else
        echo "✗ CONFIG_${option}=${actual} (expected: ${expected})"
        return 1
    fi
}

VERIFY_OK=true

# RT and performance settings
check_config "PREEMPT_RT" "y" || VERIFY_OK=false
check_config "HZ_2000" "y" || VERIFY_OK=false
check_config "HZ" "2000" || VERIFY_OK=false
check_config "HIGH_RES_TIMERS" "y" || VERIFY_OK=false
check_config "NO_HZ_FULL" "y" || VERIFY_OK=false
check_config "RCU_BOOST" "y" || VERIFY_OK=false
check_config "DEBUG_INFO_NONE" "y" || VERIFY_OK=false
check_config "NR_CPUS" "24" || VERIFY_OK=false

# CIFS verification
echo ""
echo "=== CIFS Configuration ==="
check_config "CIFS" "m" || VERIFY_OK=false
check_config "CIFS_XATTR" "y" || VERIFY_OK=false
check_config "CIFS_POSIX" "y" || VERIFY_OK=false
check_config "CIFS_UPCALL" "y" || VERIFY_OK=false

# Verify patches were applied to source files
echo ""
echo "=== Source Code Patches ==="
HZ_2000_CHECK=$(grep -c "config HZ_2000" "$KCONFIG_HZ")
ATO_BITS_CHECK=$(grep "^#define[[:space:]]*ATO_BITS" "$INET_SOCK_H" | awk '{print $3}')

if [ "$HZ_2000_CHECK" -ge 1 ]; then
    echo "✓ HZ_2000 option present in Kconfig.hz"
else
    echo "✗ HZ_2000 option missing from Kconfig.hz"
    VERIFY_OK=false
fi

if [ "$ATO_BITS_CHECK" = "10" ]; then
    echo "✓ ATO_BITS set to 10 in inet_connection_sock.h"
else
    echo "✗ ATO_BITS is $ATO_BITS_CHECK (expected 10)"
    VERIFY_OK=false
fi

echo ""
echo "=== Configuration Summary ==="
echo "Architecture: $CPU_MODEL"
if [ "$IS_ZEN4" = true ]; then
    echo "Optimizations: Zen4 (-march=x86-64-v4 -mtune=znver4 -O3) ✓"
else
    echo "Optimizations: Standard (generic x86_64)"
fi
echo "PREEMPT_RT: ENABLED ✓"
echo "HZ: 2000 ✓"
echo "ATO_BITS: 10 ✓"
echo "CIFS/SMB: ENABLED (module) ✓"
echo "Debug symbols: DISABLED ✓"
echo "NR_CPUS: 24 ✓"
echo ""

if [ "$VERIFY_OK" = false ]; then
    echo "⚠ WARNING: Some verification checks failed"
    echo ""
    read -p "Continue with build anyway? [y/N] " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "Build cancelled. You can:"
        echo "  - Review .config manually: make menuconfig"
        echo "  - Check patches: cat ${KCONFIG_HZ}.backup"
        echo "  - Restore config: cp .config.backup .config"
        exit 1
    fi
fi

# ============================================
# Final confirmation before build
# ============================================

read -p "Configuration complete. Proceed with build? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "Build cancelled. Configuration saved in .config"
    echo "To build later, run:"
    if [ "$IS_ZEN4" = true ]; then
        echo "  make KCFLAGS=\"-march=x86-64-v4 -mtune=znver4 -O3\" -j\$(nproc)"
    else
        echo "  make -j\$(nproc)"
    fi
    exit 0
fi

# ============================================
# Build kernel
# ============================================

echo ""
echo "=== Building Kernel ==="
if [ -n "$KCFLAGS" ]; then
    echo "Compiler flags: $KCFLAGS"
fi
echo "Parallel jobs: $(nproc)"
echo "Started: $(date)"
echo ""
START_TIME=$(date +%s)

# Build kernel with architecture-specific flags
if [ "$IS_ZEN4" = true ]; then
    echo "Building with Zen4 optimizations..."
    make KCFLAGS="-march=x86-64-v4 -mtune=znver4 -O3" -j$(nproc) || {
        echo "✗ Kernel build failed!"
        exit 1
    }
else
    echo "Building with standard flags..."
    make -j$(nproc) || {
        echo "✗ Kernel build failed!"
        exit 1
    }
fi

# Build RPM package
echo ""
echo "=== Building RPM Package ==="
if [ "$IS_ZEN4" = true ]; then
    make KCFLAGS="-march=x86-64-v4 -mtune=znver4 -O3" -j$(nproc) binrpm-pkg || {
        echo "⚠ RPM package build failed, but kernel image is OK"
    }
else
    make -j$(nproc) binrpm-pkg || {
        echo "⚠ RPM package build failed, but kernel image is OK"
    }
fi

END_TIME=$(date +%s)
BUILD_TIME=$((END_TIME - START_TIME))
BUILD_MIN=$((BUILD_TIME / 60))
BUILD_SEC=$((BUILD_TIME % 60))

echo ""
echo "=== Build Complete ==="
echo "Finished: $(date)"
echo "Build time: ${BUILD_MIN}m ${BUILD_SEC}s"
echo ""

# ============================================
# Show results
# ============================================

if [ -f arch/x86/boot/bzImage ]; then
    echo "=== Kernel Image ==="
    ls -lh arch/x86/boot/bzImage
    KERNEL_SIZE=$(stat -c%s arch/x86/boot/bzImage)
    KERNEL_MB=$((KERNEL_SIZE / 1024 / 1024))
    echo "Size: ${KERNEL_MB} MB"
    echo ""
   
    if [ $KERNEL_MB -lt 20 ]; then
        echo "✓ Size optimal (expected: 10-15 MB with RT)"
    elif [ $KERNEL_MB -lt 50 ]; then
        echo "⚠ Size acceptable but larger than expected"
        echo "  Consider checking if debug symbols are fully disabled"
    else
        echo "✗ Size too large (${KERNEL_MB} MB)"
        echo "  Debug symbols may still be enabled!"
        echo "  Check: grep DEBUG_INFO .config"
    fi
else
    echo "✗ Error: Kernel image not found!"
    echo "Build may have failed"
    exit 1
fi

echo ""
echo "=== RPM Packages ==="
RPM_DIR="${PWD}/rpmbuild/RPMS/x86_64"
if [ -d "$RPM_DIR" ]; then
    RPM_COUNT=$(find "$RPM_DIR" -name "kernel*.rpm" -mtime -1 2>/dev/null | wc -l)
    if [ "$RPM_COUNT" -gt 0 ]; then
        echo "Found $RPM_COUNT package(s):"
        find "$RPM_DIR" -name "kernel*.rpm" -mtime -1 -exec ls -lh {} \;
    else
        echo "⚠ No recent RPM packages found"
        echo "Check: ls -la $RPM_DIR"
    fi
else
    echo "⚠ RPM directory not found: $RPM_DIR"
    echo "RPM package may not have been created"
fi

echo ""
echo "=== Optimizations Applied ==="
echo "✓ HZ=2000 (0.5ms timer resolution)"
echo "✓ PREEMPT_RT (real-time scheduling)"
echo "✓ ATO_BITS=10 (better network ACK handling)"
echo "✓ CIFS/SMB support (module)"
echo "✓ Debug info removed (97% size reduction)"
echo "✓ BBR TCP congestion control"
if [ "$IS_ZEN4" = true ]; then
    echo "✓ Zen4 optimizations:"
    echo "  • -march=x86-64-v4 (AVX-512, AVX2, FMA, BMI)"
    echo "  • -mtune=znver4 (Zen4 instruction scheduling)"
    echo "  • -O3 (aggressive optimization)"
fi
echo ""
echo "=== Performance Expectations ==="
echo "Audio latency: <5ms ✓"
echo "Network latency: Improved ✓"
echo "Real-time performance: Optimal ✓"
echo "CIFS/SMB mounts: Supported ✓"
if [ "$IS_ZEN4" = true ]; then
    echo "CPU performance: +10-20% (Zen4 optimized) ✓"
fi
echo ""
echo "=== Installation Steps ==="
if [ -d "$RPM_DIR" ] && [ "$RPM_COUNT" -gt 0 ]; then
    echo "1. sudo rpm -ivh $RPM_DIR/kernel-*.rpm"
    echo "2. sudo grub2-mkconfig -o /boot/grub2/grub.cfg"
else
    echo "1. sudo make modules_install"
    echo "2. sudo make install"
fi
echo "3. sudo reboot"
echo "4. Select new kernel from GRUB menu"
echo ""
echo "=== Verification After Boot ==="
echo "# Check kernel version and config:"
echo "uname -r"
echo "grep CONFIG_HZ= /boot/config-\$(uname -r)"
echo "grep CONFIG_PREEMPT_RT /boot/config-\$(uname -r)"
echo ""
echo "# Verify CIFS module:"
echo "modinfo cifs"
echo "lsmod | grep cifs"
echo ""
echo "# Test CIFS mount (example):"
echo "sudo mount -t cifs //server/share /mnt/point -o username=user"
echo ""
echo "# Check patches applied:"
echo "grep ATO_BITS /usr/src/kernels/\$(uname -r)/include/net/inet_connection_sock.h"
echo ""
if [ "$IS_ZEN4" = true ]; then
    echo "# Verify Zen4 optimizations:"
    echo "cat /proc/cpuinfo | grep -E 'avx512|avx2' | head -1"
fi
echo ""
echo "=== Backup Files Created ==="
echo ".config.backup - Kernel configuration backup"
echo "${KCONFIG_HZ}.backup - Original Kconfig.hz"
echo "${INET_SOCK_H}.backup - Original inet_connection_sock.h"

Et pour ceux qui sont tentés par l'optimisation de leur serveur sous Linux, voici la façon que j'ai trouvée optimale d'isoler les processeurs et de les affecter aux tâches HQPlayer et direttaAlsa.

Cette façon de procéder est compatible avec les dernières versions du noyau et permet une cohabitation harmonieuse de HQPlayer et de DirettaAlsa.

Voir ici la référence de départ: https://documentation.ubuntu.com/real-ti...st/how-to/

CPU Isolation Strategy for Real-Time Audio Processing

A Modern, Persistent Approach Using Systemd Slices and Cgroups v2

---

Overview

This guide implements CPU isolation for real-time audio workloads (HQPlayer, Diretta) on Fedora/Ubuntu with RT kernels. It leverages systemd slices and cgroup v2 for robust, persistent isolation that survives reboots and updates.

Key Benefits:
- [x] Persistence across reboots
- [x] Systemd-native configuration
- [x] Minimal latency for audio processing
- [x] Proper inheritance to subprocesses/threads

---

System Architecture

Target System: AMD Ryzen 7 7700X (16 logical CPUs: 8 cores × 2 threads)

CPU Allocation:
- CPUs 0, 8: Housekeeping (IRQs, system tasks)
- CPUs 1-2, 9-10: Diretta ALSA (2 cores + SMT)
- CPUs 3-7, 11-15: HQPlayer (5 cores + SMT)

---

Prerequisites

### Stop Running Services
Code :
sudo systemctl stop hqplayerd
sudo systemctl stop diretta_sync_host  # Adjust name as needed

### Backup Existing Configurations
Code :
sudo cp /lib/systemd/system/multi-user.target.wants/hqplayerd.service \
      /lib/systemd/system/multi-user.target.wants/hqplayerd.service.bak

### Verify Cgroup v2
Code :
cat /sys/fs/cgroup/cgroup.controllers
# Should list "cpuset" among controllers

---

## Step 1: Kernel Boot Parameters

Edit GRUB configuration:
Code :
sudo nano /etc/default/grub

Add/modify the following line:
Code :
GRUB_CMDLINE_LINUX="rhgb quiet zswap.enabled=0 amd_pstate=enable audit=0 ibt=off nosoftlockup skew_tick=1 default_hugepagesz=1G isolcpus=io_queue,1-7,9-15 nohz=on nohz_full=1-7,9-15 rcu_nocbs=1-7,9-15 irqaffinity=0,8"

**Parameter Explanation:**
- isolcpus=io_queue,1-7,9-15 - Isolates CPUs from general scheduler
- nohz_full=1-7,9-15 - Disables periodic timer ticks (reduces interrupts)
- rcu_nocbs=1-7,9-15 - Offloads RCU callbacks to housekeeping CPUs
- irqaffinity=0,8 - Restricts hardware interrupts to CPUs 0 and 8

Update GRUB and reboot:
Code :
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
sudo reboot

---

## Step 2: Create Systemd Configuration Directories

Code :
sudo mkdir -p /etc/systemd/system/init.scope.d/
sudo mkdir -p /etc/systemd/system/system.slice.d/
sudo mkdir -p /etc/systemd/system/user.slice.d/

---

## Step 3: Restrict System Tasks to Housekeeping CPUs

### Init Scope Configuration
Code :
sudo nano /etc/systemd/system/init.scope.d/50-cpu-isolation.conf

Code :
[Scope]
AllowedCPUs=0,8

### System Slice Configuration
Code :
sudo nano /etc/systemd/system/system.slice.d/50-cpu-isolation.conf

Code :
[Slice]
AllowedCPUs=0,8

### User Slice Configuration
Code :
sudo nano /etc/systemd/system/user.slice.d/50-cpu-isolation.conf

Code :
[Slice]
AllowedCPUs=0,8

---

## Step 4: Create Custom Workload Slices

### Diretta Slice
Code :
sudo nano /etc/systemd/system/diretta.slice

Code :
[Slice]
AllowedCPUs=1-2,9-10

### HQPlayer Slice
Code :
sudo nano /etc/systemd/system/hqplayer.slice

Code :
[Slice]
AllowedCPUs=3-7,11-15
CPUQuota=100%

---

## Step 5: Configure Service Files

### Diretta ALSA Service
Code :
sudo nano /etc/systemd/system/diretta_sync_host.service

Code :
[Unit]
Description=Diretta Synchro ALSA Host
After=network-online.target
ConditionPathExists=/home/User/DirettaAlsaHost

[Service]
Slice=diretta.slice
ExecStart=/home/User/DirettaAlsaHost/syncAlsa_gcc15_x64_zen4 /home/User/DirettaAlsaHost/setting.inf
ExecStop=/home/User/DirettaAlsaHost/syncAlsa_gcc15_x64_zen4 kill
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target

### HQPlayer Service
Code :
sudo nano /etc/systemd/system/multi-user.target.wants/hqplayerd.service

Code :
[Unit]
Description=HQPlayer Embedded daemon
Requires=network-online.target sound.target systemd-udev-settle.service NetworkManager-wait-online.service
After=network-online.target sound.target systemd-udev-settle.service local-fs.target remote-fs.target

[Service]
Type=simple
Slice=hqplayer.slice
ExecStart=/usr/bin/hqplayerd
Restart=always
RestartSec=2
EnvironmentFile=-/etc/default/hqplayerd
User=hqplayer
IOSchedulingClass=realtime
LimitMEMLOCK=4G
LimitNICE=-10
LimitRTPRIO=98
CPUSchedulingPolicy=rr
CPUSchedulingPriority=99
Nice=-20

[Install]
WantedBy=multi-user.target

**Key Settings:**
- Slice=hqplayer.slice - Assigns to custom slice with isolated CPUs
- CPUSchedulingPolicy=rr - Real-time round-robin scheduling
- CPUSchedulingPriority=99 - Maximum RT priority
- LimitMEMLOCK=4G - Prevents memory paging

---

## Step 6: IRQ Affinity Management

### Create IRQ Affinity Script
Code :
sudo nano /usr/local/bin/set-irq-affinity.sh

Code :
#!/bin/bash
# Set IRQ affinities to housekeeping cores for isolation

HOUSEKEEPING_CPUS="0,8"
LOG_FILE="/var/log/irq-affinity.log"

echo "$(date): Starting IRQ affinity setup" | tee -a "$LOG_FILE"

# Set global default affinity
echo "$HOUSEKEEPING_CPUS" > /proc/irq/default_smp_affinity_list 2>> "$LOG_FILE" && \
    echo "Set default IRQ affinity to $HOUSEKEEPING_CPUS" | tee -a "$LOG_FILE" || \
    echo "Error setting default affinity" | tee -a "$LOG_FILE"

# Set affinity for all existing IRQs
for irq_dir in /proc/irq/*; do
    if [ -f "$irq_dir/smp_affinity_list" ]; then
        irq=$(basename "$irq_dir")
        echo "$HOUSEKEEPING_CPUS" > "$irq_dir/smp_affinity_list" 2>> "$LOG_FILE" && \
            echo "Set IRQ $irq to $HOUSEKEEPING_CPUS" | tee -a "$LOG_FILE" || \
            echo "Error setting IRQ $irq" | tee -a "$LOG_FILE"
    fi
done

# Show current IRQ mappings
echo "" | tee -a "$LOG_FILE"
echo "Current IRQ affinity:" | tee -a "$LOG_FILE"
for i in $(find /proc/irq/ -name smp_affinity_list | grep -v "default_smp_affinity"); do
    irq=$(basename $(dirname $i))
    affinity=$(cat $i)
    echo "IRQ $irq: $affinity" | tee -a "$LOG_FILE"
done

Make executable:
Code :
sudo chmod +x /usr/local/bin/set-irq-affinity.sh

### Create Systemd Service
Code :
sudo nano /etc/systemd/system/set-irq-affinity.service

Code :
[Unit]
Description=Set IRQ affinity for audio isolation
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/set-irq-affinity.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Enable the service:
Code :
sudo systemctl daemon-reload
sudo systemctl enable set-irq-affinity.service

---

## Step 7: CPU Frequency Scaling

### Create Performance Governor Service
Code :
sudo nano /etc/systemd/system/cpu-performance.service

Code :
[Unit]
Description=Set CPU governor to performance for audio cores
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'for i in 1 2 3 4 5 6 7 9 10 11 12 13 14 15; do echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor; done'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Enable:
Code :
sudo systemctl daemon-reload
sudo systemctl enable cpu-performance.service

---

## Step 8: Apply Configuration

Code :
sudo systemctl daemon-reload
sudo systemctl restart hqplayerd
sudo systemctl restart diretta_sync_host
sudo systemctl start set-irq-affinity.service
sudo systemctl start cpu-performance.service

---

## Step 9: Verification

### Check CPU Affinity
Code :
# HQPlayer threads
ps -eLo psr,comm | grep hqplayerd | awk '{print $1}' | sort -nu

# Diretta threads
ps -eLo psr,comm | grep syncAlsa | awk '{print $1}' | sort -nu

# Expected: HQPlayer on 3-7,11-15; Diretta on 1-2,9-10

### Verify Systemd Configuration
Code :
# Check slice settings
systemctl show hqplayer.slice -p AllowedCPUs
systemctl show diretta.slice -p AllowedCPUs
systemctl show system.slice -p AllowedCPUs

# Check service inheritance
systemctl show hqplayerd -p AllowedCPUs
systemctl show diretta_sync_host -p AllowedCPUs

### Check IRQ Distribution
Code :
# View IRQ affinity log
sudo tail -n 50 /var/log/irq-affinity.log

# Check specific IRQ
cat /proc/interrupts | grep -E "CPU0|CPU8"

### Verify CPU Governor
Code :
for i in {1..7} {9..15}; do
    echo "CPU $i: $(cat /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor)"
done

---

## Step 10: Performance Testing

### Latency Test with Cyclictest
Code :
sudo ./cyclictest -q -l 600000 -m -Sp98 -i100 -d0

**Target Metrics:**
- Max latency < 50μs on isolated CPUs
- Consistent performance during audio playback

### Monitor During Playback
Code :
# Real-time CPU usage
htop -d 5

# Per-thread affinity
watch -n 1 'ps -eLo pid,tid,psr,comm,args | grep -E "hqplayer|syncAlsa"'

---

## Troubleshooting

### Configuration Not Applied

**Check systemd loaded configurations:**
Code :
systemctl cat init.scope
systemctl cat system.slice
systemctl cat hqplayer.slice

**Verify cgroup effective CPUs:**
Code :
cat /sys/fs/cgroup/system.slice/cpuset.cpus.effective
cat /sys/fs/cgroup/hqplayer.slice/cpuset.cpus.effective

### Services on Wrong CPUs

**Force daemon reload:**
Code :
sudo systemctl daemon-reload
sudo systemctl restart system.slice  # Warning: Restarts all system services

**Check for conflicting configurations:**
Code :
systemd-delta --type=extended | grep -E "slice|scope"

### Reverting Changes

**Remove configuration files:**
Code :
sudo rm -rf /etc/systemd/system/init.scope.d/
sudo rm -rf /etc/systemd/system/system.slice.d/
sudo rm -rf /etc/systemd/system/user.slice.d/
sudo rm /etc/systemd/system/diretta.slice
sudo rm /etc/systemd/system/hqplayer.slice
sudo systemctl daemon-reload

**Restore original kernel parameters:**
Code :
sudo nano /etc/default/grub
# Remove isolation parameters
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
sudo reboot

---

## Technical Notes

### Why This Approach Works

  1. Cgroup v2 Hierarchy: AllowedCPUs in slices creates hard CPU boundaries that inherit to all child processes/threads
  2. Kernel Isolation: isolcpus prevents scheduler from automatically placing tasks on isolated CPUs
  3. RT Scheduling: SCHED_RR priority 99 ensures audio tasks preempt all normal-priority work
Répondre
#30
Pour vous permettre de faire vos premiers pas dans l'optimisation de Diretta en mode DDS, voici un programme python qui calcule une proposition de fichier de paramètres adaptés. N'oubliez pas de démarrer à très bas volume pour ne pas griller vos enceintes. Je dégage toute responsabilité...


Code :
#!/usr/bin/env python3
"""
Diretta DDS Configuration Calculator
Based on real working configuration with adaptive CycleTime
Optimized settings: periodMin=4, periodMax=8, syncBufferCount=6

Usage:
    python3 diretta_calc.py                    # Default optimized settings
    python3 diretta_calc.py --period-max 6    # Lower latency
    python3 diretta_calc.py --pcm              # PCM instead of DSD
    python3 diretta_calc.py --help            # Show all options
"""

import argparse
from typing import Dict, List, Tuple

class DirettaCalculator:
    """Calculate Diretta configuration parameters"""
   
    # Ethernet frame overhead
    ETH_HEADER = 14
    DIRETTA_HEADER = 2
    VLAN_OVERHEAD = 4
    FCS = 4
   
    def __init__(self, mtu: int = 9024):
        self.mtu = mtu
        self.overhead = self.ETH_HEADER + self.DIRETTA_HEADER + self.VLAN_OVERHEAD
        self.available_payload = mtu - self.overhead
       
    def calculate_frame_params(self, sample_rate: int, is_dsd: bool = True) -> Dict:
        """
        Calculate frame parameters for a given sample rate
       
        Args:
            sample_rate: Sample rate in Hz (e.g., 12288000 for DSD256×48k)
            is_dsd: True for DSD, False for PCM
       
        Returns:
            Dictionary with frame parameters
        """
        # Bytes per sample (stereo)
        if is_dsd:
            bytes_per_sample = 0.25  # 1 bit/sample × 2 channels = 2 bits = 0.25 bytes
        else:
            bytes_per_sample = 6  # 24 bit/sample × 2 channels = 48 bits = 6 bytes
       
        # Calculate samples that fit in available payload
        # Align to 64-bit (8 byte) boundary
        audio_bytes_max = (int(self.available_payload / 8) * 8)
        samples_per_frame = int(audio_bytes_max / bytes_per_sample)
       
        # Actual audio bytes after alignment
        audio_bytes = int(samples_per_frame * bytes_per_sample)
       
        # Calculate cycle time (time to transmit one frame)
        cycle_time_us = (samples_per_frame / sample_rate) * 1_000_000
       
        # Packet rate (packets per second)
        packet_rate_hz = sample_rate / samples_per_frame
       
        # Total frame size
        total_frame_size = self.ETH_HEADER + self.DIRETTA_HEADER + audio_bytes + self.FCS
       
        return {
            'sample_rate': sample_rate,
            'sample_rate_mhz': sample_rate / 1_000_000,
            'samples_per_frame': samples_per_frame,
            'audio_bytes': audio_bytes,
            'total_frame_size': total_frame_size,
            'cycle_time_us': cycle_time_us,
            'cycle_time_ms': cycle_time_us / 1000,
            'packet_rate_hz': packet_rate_hz,
            'bytes_per_sample': bytes_per_sample,
            'is_dsd': is_dsd,
        }
   
    def find_target_cycle_time(self, base_rates: List[int], is_dsd: bool = True) -> Tuple[int, Dict]:
        """
        Find a target CycleTime that works well across multiple base rates
       
        Args:
            base_rates: List of base sample rates (e.g., [44100, 48000])
            is_dsd: True for DSD, False for PCM
       
        Returns:
            Tuple of (recommended_cycle_time_us, analysis_dict)
        """
        results = {}
       
        for base_rate in base_rates:
            # For DSD256, multiply by 256; for PCM 8fs, multiply by 8
            multiplier = 256 if is_dsd else 8
            sample_rate = base_rate * multiplier
           
            params = self.calculate_frame_params(sample_rate, is_dsd)
            results[base_rate] = params
       
        # Find the cycle time that's closest to average
        cycle_times = [p['cycle_time_us'] for p in results.values()]
        avg_cycle = sum(cycle_times) / len(cycle_times)
       
        # Round to nearest 5 microseconds for cleaner config
        target_cycle = int(round(avg_cycle / 5) * 5)
       
        return target_cycle, results


def print_header():
    """Print program header"""
    print("""
╔═══════════════════════════════════════════════════════════════════════════════╗
║                  DIRETTA DDS CONFIGURATION CALCULATOR                        ║
║                        Low Latency Optimizer                                ║
╚═══════════════════════════════════════════════════════════════════════════════╝
""")


def print_analysis_table(calculator: DirettaCalculator, configs: List[Dict]):
    """Print analysis table for different sample rates"""
   
    print(f"\n{'='*100}")
    print(f"SAMPLE RATE ANALYSIS (MTU = {calculator.mtu} bytes)")
    print(f"{'='*100}")
   
    print(f"\n{'Format':<20} {'Sample Rate':<15} {'Samples/':<12} {'Cycle':<12} {'Packet':<12} {'Audio':<10}")
    print(f"{'':20} {'(MHz)':<15} {'Frame':<12} {'(μs)':<12} {'Rate (Hz)':<12} {'Bytes':<10}")
    print("-" * 100)
   
    for config in configs:
        params = calculator.calculate_frame_params(config['sample_rate'], config['is_dsd'])
       
        print(f"{config['name']:<20} "
              f"{params['sample_rate_mhz']:>8.6f}      "
              f"{params['samples_per_frame']:>8}    "
              f"{params['cycle_time_us']:>8.1f}    "
              f"{params['packet_rate_hz']:>8.2f}    "
              f"{params['audio_bytes']:>6}")


def print_latency_table(calculator: DirettaCalculator, configs: List[Dict],
                      period_min: int, period_max: int, sync_buffer: int):
    """Print detailed latency table for all configurations"""
   
    print(f"\n{'='*100}")
    print(f"LATENCY COMPARISON TABLE")
    print(f"{'='*100}")
   
    buffer_configs = [
        ("Ultra Conservative", 6, 12, 10),
        ("Conservative", 5, 10, 8),
        ("Optimized (recommended)", 4, 8, 6),
        ("Lower Latency", 3, 6, 5),
        ("Aggressive", 3, 6, 4),
    ]
   
    # Highlight the current settings
    current_config = (f"Your Settings", period_min, period_max, sync_buffer)
   
    print(f"\n{'Configuration':<25} {'Periods':<12} {'Sync':<8} {'48kHz':<12} {'44.1kHz':<12} {'Notes'}")
    print(f"{'':25} {'(min/max)':<12} {'Buf':<8} {'Latency':<12} {'Latency':<12}")
    print("-" * 100)
   
    # Find DSD256 configs for latency calculation
    dsd256_48k = None
    dsd256_441k = None
    for config in configs:
        if config['sample_rate'] == 12288000:
            dsd256_48k = calculator.calculate_frame_params(config['sample_rate'], True)
        elif config['sample_rate'] == 11289600:
            dsd256_441k = calculator.calculate_frame_params(config['sample_rate'], True)
   
    for name, pmin, pmax, sync in buffer_configs:
        lat_48k = dsd256_48k['cycle_time_ms'] * pmax if dsd256_48k else 0
        lat_441k = dsd256_441k['cycle_time_ms'] * pmax if dsd256_441k else 0
       
        is_current = (pmin == period_min and pmax == period_max and sync == sync_buffer)
        marker = ">>> " if is_current else "    "
       
        notes = ""
        if pmax >= 10:
            notes = "Very stable"
        elif pmax == 8:
            notes = "Good balance"
        elif pmax == 6:
            notes = "Monitor closely"
        else:
            notes = "Risky!"
       
        print(f"{marker}{name:<21} "
              f"{pmin:>3}/{pmax:<7} "
              f"{sync:>4}    "
              f"{lat_48k:>7.2f} ms  "
              f"{lat_441k:>7.2f} ms  "
              f"{notes}")
   
    # Add your current settings if they're custom
    if not any(pmin == period_min and pmax == period_max and sync == sync_buffer
              for _, pmin, pmax, sync in buffer_configs):
        lat_48k = dsd256_48k['cycle_time_ms'] * period_max if dsd256_48k else 0
        lat_441k = dsd256_441k['cycle_time_ms'] * period_max if dsd256_441k else 0
       
        print(f">>> Your Settings        "
              f"{period_min:>3}/{period_max:<7} "
              f"{sync_buffer:>4}    "
              f"{lat_48k:>7.2f} ms  "
              f"{lat_441k:>7.2f} ms  "
              f"Custom")


def print_improvement_comparison():
    """Show improvement from conservative to optimized settings"""
    print(f"\n{'='*100}")
    print("LATENCY IMPROVEMENT: Conservative → Optimized")
    print(f"{'='*100}")
   
    print("\nConservative Settings (periodMin=5, periodMax=10, syncBufferCount=8):")
    print("  48kHz family:  ~29.4 ms")
    print("  44.1kHz family: ~32.0 ms")
   
    print("\nOptimized Settings (periodMin=4, periodMax=8, syncBufferCount=6):")
    print("  48kHz family:  ~23.5 ms  (↓ 5.9 ms, 20% faster)")
    print("  44.1kHz family: ~25.6 ms  (↓ 6.4 ms, 20% faster)")
   
    print("\nWhat Changed:")
    print("  • periodMax:      10 → 8  (2 fewer periods)")
    print("  • periodMin:        5 → 4  (tighter ratio)")
    print("  • syncBufferCount:  8 → 6  (2 fewer buffers)")
    print("  • CycleTime:    2935 μs    (unchanged - proven stable)")
   
    print("\nStability Analysis:")
    print("  ✓ periodMin/Max ratio: 4:8 = 1:2  (good balance)")
    print("  ✓ Total buffering: 8 periods (reasonable)")
    print("  ✓ Sync buffer: 6 (adequate for clock drift)")
    print("  ⚠ Monitor for underruns on congested networks")


def generate_config(cycle_time: int, period_min: int = 4, period_max: int = 8,
                  period_size_min: int = 2048, period_size_max: int = 8192,
                  sync_buffer: int = 6, latency_buffer: int = 0,
                  thred_mode: int = 257, interface: str = 'enp5s0',
                  cpu_send: int = 1, cpu_other: int = 2,
                  margin_us: int = 20) -> str:
    """Generate Diretta configuration file content"""
   
    cycle_min = cycle_time - margin_us
   
    config = f"""[global]
Interface={interface}
TargetProfileLimitTime=0
ThredMode={thred_mode}
InfoCycle=100000
FlexCycle=max
CycleTime={cycle_time}
CycleMinTime={cycle_min}
Debug=stdout
periodMax={period_max}
periodMin={period_min}
periodSizeMax={period_size_max}
periodSizeMin={period_size_min}
syncBufferCount={sync_buffer}
alsaUnderrun=enable
unInitMemDet=disable
CpuSend={cpu_send}
CpuOther={cpu_other}
LatencyBuffer={latency_buffer}
"""
    return config


def print_usage_guide():
    """Print usage and monitoring guide"""
    print(f"\n{'='*100}")
    print("USAGE GUIDE")
    print(f"{'='*100}")
   
    print("""
1. SAVE CONFIGURATION
  sudo nano ~/DirettaAlsaHost/setting.inf
  (paste the configuration shown above)

2. RESTART DIRETTA
  sudo systemctl restart diretta_sync_host.service

3. MONITOR OPERATION
  journalctl -u diretta_sync_host -f
 
  Look for these indicators:
  ✓ "start cycle=XXXXusec" - shows actual cycle time
  ✓ "info rcv" - timing statistics (should be stable)
  ✗ "Buffer underrun" - indicates buffers too small
  ✗ Timing jitter >100μs - network congestion

4. VERIFY EXPECTED BEHAVIOR
  • CycleTime will auto-adjust per sample rate
  • 48kHz: ~2938 μs (340 packets/sec)
  • 44.1kHz: ~3198 μs (313 packets/sec)
  • This is normal and expected!

5. TROUBLESHOOTING
  Buffer underruns occur:
    → Increase periodMax: --period-max 10
    → Increase syncBuffer: --sync-buffer 8
 
  Want lower latency:
    → Decrease periodMax: --period-max 6
    → Decrease syncBuffer: --sync-buffer 5
    → Monitor closely for underruns!

6. NETWORK OPTIMIZATION
  • Ensure jumbo frames enabled: ip link set enp5s0 mtu 9024
  • Disable offloading: ethtool -K enp5s0 gro off lro off
  • Check no packet loss: ethtool -S enp5s0 | grep errors
  • Isolate Diretta traffic on dedicated network
""")


def print_key_concepts():
    """Explain key concepts"""
    print(f"\n{'='*100}")
    print("KEY CONCEPTS EXPLAINED")
    print(f"{'='*100}")
   
    print("""
CYCLE TIME (Adaptive)
  • You configure: CycleTime=2935 (target value)
  • Diretta adjusts: Actual cycle varies by sample rate
  • Purpose: Maintains constant packet size (9024 bytes)
  • Why adaptive: Different sample rates need different timing

PERIOD BUFFERS
  • periodMin/Max: Range of buffering depth
  • Each period = one CycleTime
  • periodMax determines total latency
  • Example: 8 periods × 2.938 ms = 23.5 ms latency

SYNC BUFFER
  • syncBufferCount: Additional buffer for clock sync
  • Compensates for clock drift between sender/receiver
  • Too small: Sync issues, clicks/pops
  • Too large: Added latency

PACKET STRUCTURE
  • Total frame: 9024 bytes (jumbo frame)
  • Overhead: 20 bytes (ethernet + diretta headers)
  • Audio payload: ~9004 bytes
  • Samples per packet: Varies by sample rate

LATENCY CALCULATION
  • Total latency = CycleTime × periodMax
  • Does NOT include:
    - DAC processing time
    - Network propagation delay (usually <1ms)
    - USB/SPDIF converter latency
  • Actual end-to-end: Add ~2-5ms for complete chain
""")


def main():
    parser = argparse.ArgumentParser(
        description='Diretta DDS Configuration Calculator - Optimized Settings',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s                                  # Default optimized config
  %(prog)s --period-max 6 --sync-buffer 5  # Lower latency (experimental)
  %(prog)s --period-max 10 --sync-buffer 8 # More conservative
  %(prog)s --pcm                            # PCM instead of DSD
  %(prog)s --mtu 1500                      # Standard ethernet MTU
  %(prog)s --config-only                    # Just show config file
        """
    )
   
    parser.add_argument('--mtu', type=int, default=9024,
                      help='MTU size (default: 9024 for jumbo frames)')
    parser.add_argument('--pcm', action='store_true',
                      help='Calculate for PCM instead of DSD')
    parser.add_argument('--period-min', type=int, default=4,
                      help='periodMin value (default: 4)')
    parser.add_argument('--period-max', type=int, default=8,
                      help='periodMax value (default: 8)')
    parser.add_argument('--sync-buffer', type=int, default=6,
                      help='syncBufferCount value (default: 6)')
    parser.add_argument('--latency-buffer', type=int, default=0,
                      help='LatencyBuffer value (default: 0)')
    parser.add_argument('--period-size-min', type=int, default=2048,
                      help='periodSizeMin value (default: 2048)')
    parser.add_argument('--period-size-max', type=int, default=8192,
                      help='periodSizeMax value (default: 8192)')
    parser.add_argument('--config-only', action='store_true',
                      help='Only generate config, skip analysis')
    parser.add_argument('--thred-mode', type=int, default=257,
                      help='ThredMode value (default: 257)')
    parser.add_argument('--interface', type=str, default='enp5s0',
                      help='Network interface (default: enp5s0)')
    parser.add_argument('--cpu-send', type=int, default=1,
                      help='CPU core for send thread (default: 1)')
    parser.add_argument('--cpu-other', type=int, default=2,
                      help='CPU core for other threads (default: 2)')
   
    args = parser.parse_args()
   
    calculator = DirettaCalculator(mtu=args.mtu)
    is_dsd = not args.pcm
    format_type = "DSD" if is_dsd else "PCM"
   
    # Define sample rate configurations
    if is_dsd:
        configs = [
            {'name': 'DSD256 × 48kHz', 'sample_rate': 48000 * 256, 'is_dsd': True},
            {'name': 'DSD256 × 44.1kHz', 'sample_rate': 44100 * 256, 'is_dsd': True},
            {'name': 'DSD128 × 48kHz', 'sample_rate': 48000 * 128, 'is_dsd': True},
            {'name': 'DSD128 × 44.1kHz', 'sample_rate': 44100 * 128, 'is_dsd': True},
            {'name': 'DSD64 × 48kHz', 'sample_rate': 48000 * 64, 'is_dsd': True},
            {'name': 'DSD64 × 44.1kHz', 'sample_rate': 44100 * 64, 'is_dsd': True},
        ]
    else:
        configs = [
            {'name': 'PCM 384kHz (8×48k)', 'sample_rate': 48000 * 8, 'is_dsd': False},
            {'name': 'PCM 352.8kHz (8×44.1k)', 'sample_rate': 44100 * 8, 'is_dsd': False},
            {'name': 'PCM 192kHz (4×48k)', 'sample_rate': 48000 * 4, 'is_dsd': False},
            {'name': 'PCM 176.4kHz (4×44.1k)', 'sample_rate': 44100 * 4, 'is_dsd': False},
            {'name': 'PCM 96kHz (2×48k)', 'sample_rate': 48000 * 2, 'is_dsd': False},
            {'name': 'PCM 88.2kHz (2×44.1k)', 'sample_rate': 44100 * 2, 'is_dsd': False},
        ]
   
    # Find target cycle time
    base_rates = [44100, 48000]
    target_cycle_us, analysis = calculator.find_target_cycle_time(base_rates, is_dsd)
   
    # Print analysis unless config-only
    if not args.config_only:
        print_header()
       
        print(f"Format Type: {format_type}")
        print(f"MTU: {args.mtu} bytes")
        print(f"Target CycleTime: {target_cycle_us} μs")
        print(f"\nBuffer Configuration:")
        print(f"  periodMin: {args.period_min}")
        print(f"  periodMax: {args.period_max}")
        print(f"  syncBufferCount: {args.sync_buffer}")
       
        print_analysis_table(calculator, configs)
        print_latency_table(calculator, configs, args.period_min, args.period_max, args.sync_buffer)
       
        if args.period_min == 4 and args.period_max == 8 and args.sync_buffer == 6:
            print_improvement_comparison()
       
        print_key_concepts()
   
    # Generate and display configuration
    print(f"\n{'='*100}")
    print(f"CONFIGURATION FILE ({format_type} mode)")
    print(f"{'='*100}")
   
    # Calculate expected latencies
    dsd256_48k = calculator.calculate_frame_params(12288000 if is_dsd else 384000, is_dsd)
    dsd256_441k = calculator.calculate_frame_params(11289600 if is_dsd else 352800, is_dsd)
   
    lat_48k = dsd256_48k['cycle_time_ms'] * args.period_max
    lat_441k = dsd256_441k['cycle_time_ms'] * args.period_max
   
    print(f"\nExpected Latency:")
    print(f"  48kHz family:  ~{lat_48k:.1f} ms")
    print(f"  44.1kHz family: ~{lat_441k:.1f} ms")
   
    config = generate_config(
        cycle_time=target_cycle_us,
        period_min=args.period_min,
        period_max=args.period_max,
        period_size_min=args.period_size_min,
        period_size_max=args.period_size_max,
        sync_buffer=args.sync_buffer,
        latency_buffer=args.latency_buffer,
        thred_mode=args.thred_mode,
        interface=args.interface,
        cpu_send=args.cpu_send,
        cpu_other=args.cpu_other,
    )
   
    print(config)
   
    if not args.config_only:
        print_usage_guide()
       
        print(f"\n{'='*100}")
        print("NEXT STEPS")
        print(f"{'='*100}")
        print(f"""
1. Copy the configuration above to ~/DirettaAlsaHost/setting.inf
2. Restart Diretta: sudo systemctl restart diretta_sync_host.service
3. Monitor: journalctl -u diretta_sync_host -f
4. Verify ~4ms latency achieved

For different configurations:
  • Lower latency:      python3 {__file__} --period-max 6 --sync-buffer 5
  • More conservative:  python3 {__file__} --period-max 10 --sync-buffer 8
  • Standard MTU:      python3 {__file__} --mtu 1500
  • PCM mode:          python3 {__file__} --pcm
""")


if __name__ == "__main__":
    main()
Répondre


Sujets apparemment similaires…
Sujet Auteur Réponses Affichages Dernier message
  Carte Mère SOtM - sMB-Q370 pour TARGET DIRETTA jean-luc 122 64,513 12-04-2024, 12:20 PM
Dernier message: bbill
  Soucis Windows 7 sous Mac OS Euterpe 26 8,593 10-23-2024, 09:11 AM
Dernier message: Le Moine Bleu
  Diretta Lucia Development kit Olivier 131 79,851 07-15-2024, 10:12 PM
Dernier message: Le dom
  ENGINEERED fermé ou service client sous l'eau ? Moxa 15 8,103 01-27-2024, 02:26 PM
Dernier message: thomasv
Music Room Shaper sous Win avec Roon et HQPlayer zaurux 4 4,237 11-10-2023, 12:43 AM
Dernier message: ds21

Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)