Tighten remaining audio settings to improve CI pass rate. (#1412)

* Tighten remaining audio settings to improve CI pass rate.

* Try some more changes.

* Windows: make sure mock radio is up before starting FreeDV.

* Windows: Use HP power plan on ARM.

* Don't force specific torch release.

* Revert test config file changes.

* Add PR #1412 to changelog.
pull/1380/head
Mooneer Salem 2026-06-23 15:59:56 -07:00 committed by GitHub
parent 67b7a11780
commit 737c7838e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 52 additions and 24 deletions

View File

@ -12,7 +12,6 @@ concurrency:
env: env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo BUILD_TYPE: RelWithDebInfo
TORCH_RELEASE: 2.9.1
# Needed to suppress possible cause of test errors. # Needed to suppress possible cause of test errors.
# See https://github.com/alexmurray/emacs-snap/issues/60 # See https://github.com/alexmurray/emacs-snap/issues/60
@ -130,7 +129,7 @@ jobs:
run: | run: |
python3 -m venv rade-venv python3 -m venv rade-venv
. ./rade-venv/bin/activate . ./rade-venv/bin/activate
pip3 install torch==${{ env.TORCH_RELEASE }} --index-url https://download.pytorch.org/whl/cpu pip3 install torch --index-url https://download.pytorch.org/whl/cpu
pip3 install matplotlib pip3 install matplotlib
- name: Build instrumented freedv-gui - name: Build instrumented freedv-gui
@ -349,7 +348,7 @@ jobs:
working-directory: ${{github.workspace}} working-directory: ${{github.workspace}}
run: | run: |
. ./rade-venv/bin/activate . ./rade-venv/bin/activate
pip3 install torch==${{ env.TORCH_RELEASE }} --index-url https://download.pytorch.org/whl/cpu pip3 install torch --index-url https://download.pytorch.org/whl/cpu
pip3 install matplotlib pip3 install matplotlib
- name: Sanity check RADE - name: Sanity check RADE
@ -523,7 +522,7 @@ jobs:
working-directory: ${{github.workspace}} working-directory: ${{github.workspace}}
run: | run: |
. ./rade-venv/bin/activate . ./rade-venv/bin/activate
pip3 install torch==${{ env.TORCH_RELEASE }} --index-url https://download.pytorch.org/whl/cpu pip3 install torch --index-url https://download.pytorch.org/whl/cpu
pip3 install matplotlib pip3 install matplotlib
- name: Build freedv-gui - name: Build freedv-gui
@ -562,9 +561,10 @@ jobs:
export MAX_EXECUTION_TIMES=2 export MAX_EXECUTION_TIMES=2
else else
export MAX_EXECUTION_TIMES=1 export MAX_EXECUTION_TIMES=1
fi fi
ln -s ${{github.workspace}}/build_linux/rade_src/model19_check3 model19_check3 ln -s ${{github.workspace}}/build_linux/rade_src/model19_check3 model19_check3
. ../rade-venv/bin/activate . ../rade-venv/bin/activate
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor || true
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:suppressions=${{github.workspace}}/test/ubsan_suppressions.txt ASAN_OPTIONS=suppressions=${{github.workspace}}/test/asan_suppressions.txt LSAN_OPTIONS=suppressions=${{github.workspace}}/test/lsan_suppressions.txt TSAN_OPTIONS=halt_on_error=1:ignore_noninstrumented_modules=1 PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V --repeat until-pass:$MAX_EXECUTION_TIMES UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:suppressions=${{github.workspace}}/test/ubsan_suppressions.txt ASAN_OPTIONS=suppressions=${{github.workspace}}/test/asan_suppressions.txt LSAN_OPTIONS=suppressions=${{github.workspace}}/test/lsan_suppressions.txt TSAN_OPTIONS=halt_on_error=1:ignore_noninstrumented_modules=1 PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V --repeat until-pass:$MAX_EXECUTION_TIMES
- name: Execute unit tests - name: Execute unit tests
@ -590,9 +590,10 @@ jobs:
export MAX_EXECUTION_TIMES=2 export MAX_EXECUTION_TIMES=2
else else
export MAX_EXECUTION_TIMES=1 export MAX_EXECUTION_TIMES=1
fi fi
ln -s ${{github.workspace}}/build_linux/rade_src/model19_check3 model19_check3 ln -s ${{github.workspace}}/build_linux/rade_src/model19_check3 model19_check3
. ../rade-venv/bin/activate . ../rade-venv/bin/activate
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor || true
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:suppressions=${{github.workspace}}/test/ubsan_suppressions.txt ASAN_OPTIONS=suppressions=${{github.workspace}}/test/asan_suppressions.txt LSAN_OPTIONS=suppressions=${{github.workspace}}/test/lsan_suppressions.txt TSAN_OPTIONS=halt_on_error=1:ignore_noninstrumented_modules=1 PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V --repeat until-pass:$MAX_EXECUTION_TIMES UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:suppressions=${{github.workspace}}/test/ubsan_suppressions.txt ASAN_OPTIONS=suppressions=${{github.workspace}}/test/asan_suppressions.txt LSAN_OPTIONS=suppressions=${{github.workspace}}/test/lsan_suppressions.txt TSAN_OPTIONS=halt_on_error=1:ignore_noninstrumented_modules=1 PYTHONPATH=${{github.workspace}}/build_linux/rade_src:$PYTHONPATH ctest -V --repeat until-pass:$MAX_EXECUTION_TIMES

View File

@ -263,7 +263,19 @@ jobs:
Install-Module -Name AudioDeviceCmdlets -Force -Confirm:$false Install-Module -Name AudioDeviceCmdlets -Force -Confirm:$false
Get-AudioDevice -List | where { $_.Name -eq "${{ env.MICROPHONE_TO_COMPUTER_DEVICE }}" } | Set-AudioDevice Get-AudioDevice -List | where { $_.Name -eq "${{ env.MICROPHONE_TO_COMPUTER_DEVICE }}" } | Set-AudioDevice
Get-AudioDevice -List | where { $_.Name -eq "${{ env.COMPUTER_TO_SPEAKER_DEVICE }}" } | Set-AudioDevice Get-AudioDevice -List | where { $_.Name -eq "${{ env.COMPUTER_TO_SPEAKER_DEVICE }}" } | Set-AudioDevice
- name: Set High Performance power plan to prevent CPU frequency scaling
if: ${{ matrix.runner == 'windows-11-arm' }}
shell: pwsh
run: |
# Prevent ARM CPU boost->base frequency transitions during audio tests.
# This is the Windows equivalent of the Linux "performance" CPU governor.
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
# Explicitly pin minimum processor performance to 100% so the ARM CPU
# does not scale down after exhausting its boost budget.
powercfg /setacvalueindex SCHEME_CURRENT 54533251-82be-4824-96c1-47b60b740d00 893dee8e-2bef-41e0-89c6-b55d0929964c 100
powercfg /setactive SCHEME_CURRENT
- name: Test RADE - name: Test RADE
shell: pwsh shell: pwsh
working-directory: ${{github.workspace}}\FreeDV-Install-Location\bin working-directory: ${{github.workspace}}\FreeDV-Install-Location\bin

View File

@ -959,6 +959,7 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
* Consolidate EOO length calculation in freedv-backend to improve callsign decode reliability. (PR #1402) * Consolidate EOO length calculation in freedv-backend to improve callsign decode reliability. (PR #1402)
* Hamlib: Switch off memory channel before setting frequency/mode. (PR #1403) - thanks @barjac! * Hamlib: Switch off memory channel before setting frequency/mode. (PR #1403) - thanks @barjac!
* Hamlib/OmniRig: Round received frequency to nearest 100 Hz. (PR #1373) * Hamlib/OmniRig: Round received frequency to nearest 100 Hz. (PR #1373)
* Tighten remaining audio settings to improve audio drops. (PR #1412)
2. Enhancements: 2. Enhancements:
* Add UDP broadcast of received callsigns. (PR #1367) * Add UDP broadcast of received callsigns. (PR #1367)
* Add Time-Out Timer (TOT) capability to FreeDV. (PR #1366, #1398, #1405) - thanks @barjac! * Add Time-Out Timer (TOT) capability to FreeDV. (PR #1366, #1398, #1405) - thanks @barjac!

View File

@ -685,12 +685,11 @@ void MacAudioDevice::setHelperRealTime()
THREAD_EXTENDED_POLICY, THREAD_EXTENDED_POLICY,
reinterpret_cast<thread_policy_t>(&policy), reinterpret_cast<thread_policy_t>(&policy),
THREAD_EXTENDED_POLICY_COUNT); THREAD_EXTENDED_POLICY_COUNT);
if (result != KERN_SUCCESS) if (result != KERN_SUCCESS)
{ {
log_warn("Could not set current thread to real-time: %d"); log_warn("Could not set current thread to real-time: %d", result);
return;
} }
// Set to relatively high priority. // Set to relatively high priority.
thread_precedence_policy_data_t precedence; thread_precedence_policy_data_t precedence;
precedence.importance = 63; precedence.importance = 63;
@ -700,8 +699,7 @@ void MacAudioDevice::setHelperRealTime()
THREAD_PRECEDENCE_POLICY_COUNT); THREAD_PRECEDENCE_POLICY_COUNT);
if (result != KERN_SUCCESS) if (result != KERN_SUCCESS)
{ {
log_warn("Could not increase thread priority"); log_warn("Could not increase thread priority: %d", result);
return;
} }
// Most important, set real-time constraints. // Most important, set real-time constraints.
@ -742,14 +740,12 @@ void MacAudioDevice::setHelperRealTime()
THREAD_TIME_CONSTRAINT_POLICY_COUNT); THREAD_TIME_CONSTRAINT_POLICY_COUNT);
if (result != KERN_SUCCESS) if (result != KERN_SUCCESS)
{ {
log_warn("Could not set time constraint policy"); log_warn("Could not set time constraint policy: %d", result);
return;
}
else
{
// Going real-time is a prerequisite for joining workgroups
joinWorkgroup_();
} }
// Workgroup joining improves scheduling even if time constraint policy
// could not be set above.
joinWorkgroup_();
} }
OSStatus MacAudioDevice::InputProc_( OSStatus MacAudioDevice::InputProc_(

View File

@ -27,6 +27,7 @@
#include <thread> #include <thread>
#include <future> #include <future>
#include <avrt.h> #include <avrt.h>
#include <timeapi.h>
#include <inttypes.h> #include <inttypes.h>
#include "../util/logging/ulog.h" #include "../util/logging/ulog.h"
@ -391,6 +392,10 @@ void WASAPIAudioDevice::start()
log_warn(ss.str().c_str()); log_warn(ss.str().c_str());
} }
// Reduce Windows timer resolution to 1ms to improve WaitForSingleObject
// precision in the audio loop.
timeBeginPeriod(1);
// Start render/capture // Start render/capture
hr = client_->Start(); hr = client_->Start();
if (FAILED(hr)) if (FAILED(hr))
@ -490,6 +495,8 @@ void WASAPIAudioDevice::stop()
renderClient_ = nullptr; renderClient_ = nullptr;
captureClient_ = nullptr; captureClient_ = nullptr;
timeEndPeriod(1);
if (renderCaptureEvent_ != nullptr) if (renderCaptureEvent_ != nullptr)
{ {
CloseHandle(renderCaptureEvent_); CloseHandle(renderCaptureEvent_);

View File

@ -93,6 +93,7 @@ function Test-FreeDV {
$process = New-Object System.Diagnostics.Process $process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi $process.StartInfo = $psi
[void]$process.Start() [void]$process.Start()
$process.PriorityClass = [System.Diagnostics.ProcessPriorityClass]::AboveNormal
# Read output from process # Read output from process
$err_output = $process.StandardError.ReadToEnd(); $err_output = $process.StandardError.ReadToEnd();

View File

@ -77,7 +77,7 @@ function Test-FreeDV {
$soxPsi.FileName = "sox.exe" $soxPsi.FileName = "sox.exe"
$soxPsi.WorkingDirectory = $current_loc $soxPsi.WorkingDirectory = $current_loc
$quoted_device = "`"" + $RadioToComputerDevice + "`"" $quoted_device = "`"" + $RadioToComputerDevice + "`""
$soxPsi.Arguments = @("-t waveaudio $quoted_device -c 1 -r 8000 -t wav `"$current_loc\test.wav`"") $soxPsi.Arguments = @("-t waveaudio $quoted_device -c 1 -r 48000 -t wav `"$current_loc\test.wav`"")
$soxProcess = New-Object System.Diagnostics.Process $soxProcess = New-Object System.Diagnostics.Process
$soxProcess.StartInfo = $soxPsi $soxProcess.StartInfo = $soxPsi
@ -97,7 +97,15 @@ function Test-FreeDV {
$rigctlProcess = New-Object System.Diagnostics.Process $rigctlProcess = New-Object System.Diagnostics.Process
$rigctlProcess.StartInfo = $rigctlPsi $rigctlProcess.StartInfo = $rigctlPsi
[void]$rigctlProcess.Start() [void]$rigctlProcess.Start()
# Wait for hamlibserver.py to open its listen socket before starting FreeDV,
# because Python startup on slow CI machines can take several seconds.
$deadline = (Get-Date).AddSeconds(30)
while ((Get-Date) -lt $deadline) {
if (Get-NetTCPConnection -LocalPort 4575 -State Listen -ErrorAction SilentlyContinue) { break }
Start-Sleep -Milliseconds 250
}
# Start freedv.exe # Start freedv.exe
$psi = New-Object System.Diagnostics.ProcessStartInfo $psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true $psi.CreateNoWindow = $true
@ -112,6 +120,7 @@ function Test-FreeDV {
$process = New-Object System.Diagnostics.Process $process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi $process.StartInfo = $psi
[void]$process.Start() [void]$process.Start()
$process.PriorityClass = [System.Diagnostics.ProcessPriorityClass]::AboveNormal
# Read output from first FreeDV run # Read output from first FreeDV run
$err_output = $process.StandardError.ReadToEnd(); $err_output = $process.StandardError.ReadToEnd();
@ -119,7 +128,7 @@ function Test-FreeDV {
$process.WaitForExit() $process.WaitForExit()
Write-Host "$err_output" Write-Host "$err_output"
# Stop recording audio # Stop recording audio
try { try {
$soxProcess.Kill() $soxProcess.Kill()
@ -127,13 +136,14 @@ function Test-FreeDV {
# Ignore failure as Python could have killed sox # Ignore failure as Python could have killed sox
} }
$soxProcess.WaitForExit() $soxProcess.WaitForExit()
# Restart FreeDV in RX mode # Restart FreeDV in RX mode
$psi.Arguments = @("/f $quoted_tmp_filename /ut rx /utmode RADEV1 /rxfile `"$current_loc\test.wav`"") $psi.Arguments = @("/f $quoted_tmp_filename /ut rx /utmode RADEV1 /rxfile `"$current_loc\test.wav`"")
$process = New-Object System.Diagnostics.Process $process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi $process.StartInfo = $psi
[void]$process.Start() [void]$process.Start()
$process.PriorityClass = [System.Diagnostics.ProcessPriorityClass]::AboveNormal
# Read output from second FreeDV run # Read output from second FreeDV run
$err_output_fdv = $process.StandardError.ReadToEnd() $err_output_fdv = $process.StandardError.ReadToEnd()