Compare commits

...

7 Commits

Author SHA1 Message Date
Mooneer Salem 56da90b9b1 latest user manual PDF 2026-11-01 00:22:19 +00:00
Mooneer Salem 1e062689da
User manual: Update reference to Experimental Features section. (#1613)
* User manual: Update reference to Experimental Features section.

* Add PR #1613 to changelog.
2026-10-31 17:18:57 -07:00
Mooneer Salem 102aa6e483
FreeDV Reporter: don't select the row under the mouse on focus without a click; begin 2.4.2 development (#1611)
* FreeDV Reporter: only select the row under the mouse on focus if a button is down.

OnSetFocus() selected whatever row the mouse was over whenever the list
gained the focus, including when that came from the window being brought
to the front or a tooltip closing rather than a click. On Linux the
selection guard doesn't stop this either, as hovering over a row already
allows selections. This caused an occasional gui_reporter_row_actions
failure on v3.0-dev ("Selected stations after hovering messages is
['K1ABC']").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add PR #1611 to changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Re-enable dev version tag and six-month build expiry now that 2.4.1 is out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Increment version to 2.4.2 to begin development.

Also builds against freedv-backend's main branch again instead of the
v1.0.1 release, as was done when 2.4.1 development began (#1473).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 17:11:38 -07:00
Mooneer Salem 321db15f63
Add freedv-backend bug fixes to the 2.4.1 changelog (#1608)
* Add freedv-backend bug fixes to the 2.4.1 changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add freedv-backend PR #78 fixes to the 2.4.1 changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Prepare for 2.4.1 release.

* Update freedv-backend to point to newly tagged release.

* Warn instead of refusing to start when a mic/speaker device is below 16 kHz.

FreeDV resamples every device to the rate each step needs, so an 8 kHz
mic or speaker (e.g. a Bluetooth headset using HFP's narrowband codec)
still works; it just loses audio above 4 kHz. Devices below 8 kHz are
still rejected. The warning lists the affected devices and is shown at
most once per session; each Start also logs it.

Fixes #1610.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Avoid listing duplicate device names for the Low Sample Rate warning.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:36:05 -07:00
Mooneer Salem 932b90e15f latest user manual PDF 2026-10-28 00:13:12 +00:00
Mooneer Salem 5834e2f45f
Initialize FreeDV Reporter's selection flag; fix RecordStepTest flake (#1606)
* Initialize FreeDV Reporter's selection flag; make RecordStepTest wait for the writer

isSelectionPossible_ was never initialized, so on Linux whether a
selection was honored before the pointer had been over a row depended
on whatever was in memory (caught by UBSan in gui_reporter_numeric_filters).

recordsSamplesInOrder queued bursts faster than real time with a fixed
5 ms sleep between them; on Windows runners the writer thread fell far
enough behind for the 1 s FIFO to fill and drop blocks. Wait for each
burst to be written instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

* Add release note for #1606

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019q8F5ZSDKDxXJoLJTFQ8wN

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:10:50 -07:00
Mooneer Salem 9e7d24c244 latest user manual PDF 2026-10-27 16:04:43 +00:00
8 changed files with 225 additions and 91 deletions

View File

@ -15,7 +15,7 @@ endif()
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum OS X deployment version")
set(PROJECT_NAME FreeDV)
set(PROJECT_VERSION 2.4.1)
set(PROJECT_VERSION 2.4.2)
set(PROJECT_DESCRIPTION "HF Digital Voice for Radio Amateurs")
set(PROJECT_HOMEPAGE_URL "https://freedv.org")

View File

@ -139,30 +139,30 @@ sent <strong>to</strong> your radio for transmission over the air.</p>
<col style="width: 42%" />
</colgroup>
<thead>
<tr class="header">
<tr>
<th>Tab</th>
<th>Sound Device</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>Receive Tab</td>
<td>Input To Computer From Radio</td>
<td>The off air FreeDV signal <strong>from</strong> your radio rig
interface to your computer</td>
</tr>
<tr class="even">
<tr>
<td>Receive Tab</td>
<td>Output From Computer To Speaker/Headphones</td>
<td>The decoded audio from your computer to your Speaker/Headphones</td>
</tr>
<tr class="odd">
<tr>
<td>Transmit Tab</td>
<td>Input From Microphone To Computer</td>
<td>Your voice from the microphone to your computer</td>
</tr>
<tr class="even">
<tr>
<td>Transmit Tab</td>
<td>Output From Computer To Radio</td>
<td>The FreeDV signal from your computer sent <strong>to</strong> your
@ -254,21 +254,21 @@ locations depending on platform:</p>
<col style="width: 86%" />
</colgroup>
<thead>
<tr class="header">
<tr>
<th>Platform</th>
<th>Typical Location</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>Windows</td>
<td>C:\Program Files\FreeDV [version]\share\freedv-gui\wav</td>
</tr>
<tr class="even">
<tr>
<td>Linux</td>
<td>/usr/share/freedv-gui/wav or /usr/local/share/freedv-gui/wav</td>
</tr>
<tr class="odd">
<tr>
<td>macOS</td>
<td>See https://github.com/freedv/freedv-gui/tree/master/wav</td>
</tr>
@ -379,25 +379,25 @@ untested).</p>
are below:</p>
<table>
<thead>
<tr class="header">
<tr>
<th>Mode</th>
<th>Width (kHz)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>1600</td>
<td>1.125</td>
</tr>
<tr class="even">
<tr>
<td>700D</td>
<td>1.000</td>
</tr>
<tr class="odd">
<tr>
<td>700E</td>
<td>1.500</td>
</tr>
<tr class="even">
<tr>
<td>RADEV1</td>
<td>1.500</td>
</tr>
@ -612,7 +612,7 @@ class="header-section-number">10</span> FreeDV Modes</h1>
SSB and Skype as anchors for a rough guide to audio quality:</p>
<table>
<thead>
<tr class="header">
<tr>
<th>Mode</th>
<th style="text-align: center;">Min SNR</th>
<th style="text-align: center;">Fading</th>
@ -622,7 +622,7 @@ SSB and Skype as anchors for a rough guide to audio quality:</p>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>SSB</td>
<td style="text-align: center;">0</td>
<td style="text-align: center;">8/10</td>
@ -630,7 +630,7 @@ SSB and Skype as anchors for a rough guide to audio quality:</p>
<td style="text-align: center;">2600</td>
<td style="text-align: center;">5/10</td>
</tr>
<tr class="even">
<tr>
<td>1600 (*)</td>
<td style="text-align: center;">4</td>
<td style="text-align: center;">3/10</td>
@ -638,7 +638,7 @@ SSB and Skype as anchors for a rough guide to audio quality:</p>
<td style="text-align: center;">4000</td>
<td style="text-align: center;">4/10</td>
</tr>
<tr class="odd">
<tr>
<td>700D (*)</td>
<td style="text-align: center;">-2</td>
<td style="text-align: center;">4/10</td>
@ -646,7 +646,7 @@ SSB and Skype as anchors for a rough guide to audio quality:</p>
<td style="text-align: center;">4000</td>
<td style="text-align: center;">3/10</td>
</tr>
<tr class="even">
<tr>
<td>700E (*)</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">7/10</td>
@ -654,7 +654,7 @@ SSB and Skype as anchors for a rough guide to audio quality:</p>
<td style="text-align: center;">4000</td>
<td style="text-align: center;">3/10</td>
</tr>
<tr class="odd">
<tr>
<td>RADEV1</td>
<td style="text-align: center;">-2</td>
<td style="text-align: center;">8/10</td>
@ -662,7 +662,7 @@ SSB and Skype as anchors for a rough guide to audio quality:</p>
<td style="text-align: center;">8000</td>
<td style="text-align: center;">7/10</td>
</tr>
<tr class="even">
<tr>
<td>Skype</td>
<td style="text-align: center;">-</td>
<td style="text-align: center;">-</td>
@ -781,18 +781,18 @@ class="header-section-number">11.1</span> Tools - Filter</h2>
<col style="width: 73%" />
</colgroup>
<thead>
<tr class="header">
<tr>
<th>Control</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>Noise Suppression</td>
<td>Enable noise suppression, de-reverberation, AGC of mic signal using
the Speex pre-processor</td>
</tr>
<tr class="even">
<tr>
<td>700D Auto EQ</td>
<td>Automatic equalization for FreeDV 700D/E Codec input audio</td>
</tr>
@ -821,18 +821,18 @@ class="header-section-number">11.2.1</span> Modem Options</h3>
<col style="width: 71%" />
</colgroup>
<thead>
<tr class="header">
<tr>
<th>Control</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>Clipping</td>
<td>Increases the average power. Ensure your transmitter can handle high
RMS powers before using!</td>
</tr>
<tr class="even">
<tr>
<td>TX Band Pass Filter</td>
<td>Reduces TX spectrum bandwidth</td>
</tr>
@ -876,9 +876,10 @@ the menu bar by a similar process.</p>
border and clicking and holding the left mouse button and dragging to
required size.</p>
<p>By default, the tab layout is not saved. However, by enabling
experimental features (see “Advanced/Developer Features”), experimental
support for saving and restoring the tab layout will be enabled. This
has not been well tested and may have hidden bugs or other issues.</p>
experimental features (see <a href="#experimental-features">Experimental
Features</a>), experimental support for saving and restoring the tab
layout will be enabled. This has not been well tested and may have
hidden bugs or other issues.</p>
<figure>
<img src="contrib/multiple_panes.png" alt="Multiple Panes" />
<figcaption aria-hidden="true">Multiple Panes</figcaption>
@ -890,37 +891,37 @@ class="header-section-number">14.1</span> Stats Window</h2>
<p>Located on the lower left hand side of the main screen.</p>
<table>
<thead>
<tr class="header">
<tr>
<th>Term</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>Bits</td>
<td>Number of bits demodulated</td>
</tr>
<tr class="even">
<tr>
<td>Errs</td>
<td>Number of bit errors detected</td>
</tr>
<tr class="odd">
<tr>
<td>Resyncs</td>
<td>Number of times the demodulator has resynced</td>
</tr>
<tr class="even">
<tr>
<td>ClkOff</td>
<td>Estimated sample clock offset in parts per million</td>
</tr>
<tr class="odd">
<tr>
<td>FreqOff</td>
<td>Estimated frequency offset in Hz</td>
</tr>
<tr class="even">
<tr>
<td>Sync</td>
<td>Sync metric (OFDM modes like 700D/E)</td>
</tr>
<tr class="odd">
<tr>
<td>Var</td>
<td>Speech encoder distortion for 700D (see Auto EQ)</td>
</tr>
@ -1243,23 +1244,23 @@ class="header-section-number">18</span> Glossary</h1>
<col style="width: 93%" />
</colgroup>
<thead>
<tr class="header">
<tr>
<th>Term</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<tr>
<td>AWGN</td>
<td>Additive White Gaussian Noise - a channel with just noise and no
fading (like VHF)</td>
</tr>
<tr class="even">
<tr>
<td>FEC</td>
<td>Forward Error Correction - extra bits to we send to protect the
speech codec bits</td>
</tr>
<tr class="odd">
<tr>
<td>LDPC</td>
<td>Low Density Parity Check Codes - a family of powerful FEC codes</td>
</tr>
@ -1267,8 +1268,22 @@ speech codec bits</td>
</table>
<h1 data-number="19" id="release-notes"><span
class="header-section-number">19</span> Release Notes</h1>
<h2 data-number="19.1" id="v2.4.1-tbd-2026"><span
class="header-section-number">19.1</span> V2.4.1 TBD 2026</h2>
<h2 data-number="19.1" id="v2.4.2-tbd-2026"><span
class="header-section-number">19.1</span> V2.4.2 TBD 2026</h2>
<ol type="1">
<li>Bugfixes:
<ul>
<li>FreeDV Reporter: don’t select the station under the mouse when the
list gains focus without a click. (PR #1611)</li>
</ul></li>
<li>Documentation:
<ul>
<li>User manual: Update reference to Experimental Features section. (PR
#1613)</li>
</ul></li>
</ol>
<h2 data-number="19.2" id="v2.4.1-october-2026"><span
class="header-section-number">19.2</span> V2.4.1 October 2026</h2>
<ol type="1">
<li>Bugfixes:
<ul>
@ -1303,7 +1318,7 @@ displays. (PR #1514)</li>
<li>Fix possible deadlock on playback completion. (PR #1533)</li>
<li>Windows: add logic to detect audio device stalls. (PR #1537)</li>
<li>Keep RX muted after TX until the radio confirms PTT off. (PR #1536,
#1603)</li>
#1603, #1605)</li>
<li>Fix FreeDV hanging when starting the Voice Keyer with a cloud-backed
file. (PR #1534)</li>
<li>Fix data races on settings read by the audio threads. (PR
@ -1424,6 +1439,39 @@ mode from starting. (PR #1594)</li>
<li>PlotScalar: draw the trace when the plot is wider than its sample
count. (PR #1597) - thanks <span class="citation"
data-cites="barjac">@barjac</span>!</li>
<li>Linux/FreeDV Reporter: fix uninitialized value deciding whether a
selection is honored. (PR #1606)</li>
<li>Allow microphone and speaker devices below 16 kHz (such as Bluetooth
headsets in call mode) with a warning instead of refusing to start. (PR
#1608)</li>
<li>FreeDV Reporter: fix possible crash when repeatedly connecting and
disconnecting. (freedv-backend PR #44)</li>
<li>FreeDV Reporter: fix exiting FreeDV taking up to 60 seconds when the
server stalls setting up the secure connection; give up on it after 10
seconds instead. (freedv-backend PR #63)</li>
<li>FreeDV Reporter: fix memory leak when FreeDV exits just as FreeDV
Reporter connects. (freedv-backend PR #75)</li>
<li>Recording: fix up to the last 100 ms of audio being lost when a
recording stops, and log when audio has to be dropped. (freedv-backend
PR #71, #72)</li>
<li>Fix conversion of 16-bit audio to floating point going slightly past
full scale. (freedv-backend PR #60)</li>
<li>Fix buffer overruns when one RADE receive call decodes several
frames and when resampling 8 kHz audio by large ratios. (freedv-backend
PR #78)</li>
<li>Fix the audio pipeline rebuilding its resampler when the sample rate
is unchanged but not when it changes, and freeing the kept resampler
twice. (freedv-backend PR #78)</li>
<li>FreeDV Reporter: refuse a secure connection if TLS 1.2 or
certificate hostname checking can’t be enforced. (freedv-backend PR
#78)</li>
<li>macOS/FreeDV Reporter: fix endless loop and log spam when the
connection closes while sending. (freedv-backend PR #78)</li>
<li>Fix network and threading code continuing after a failed socket or
semaphore setup, Linux semaphore waits ending early on a signal, and a
macOS crash on an empty background task. (freedv-backend PR #78)</li>
<li>Windows: fix exiting FreeDV taking 20 seconds or more while logging
heavily. (freedv-backend PR #78)</li>
</ul></li>
<li>Build system:
<ul>
@ -1443,6 +1491,14 @@ information, and only use ccache in CI for the builds that compile them.
<li>Add tests of whole transmissions through the TX/RX threads without
sound cards. (PR #1567)</li>
<li>Resolve build failure on OpenSUSE Tumbleweed. (PR #1577)</li>
<li>Fix Windows build failures with newer llvm-mingw (clang/libc++)
releases. (freedv-backend PR #51)</li>
<li>Fix Windows build with older mingw-w64 headers that don’t declare
SetThreadDescription. (freedv-backend PR #60)</li>
<li>macOS: fix RNNoise build failure with newer Xcode versions.
(freedv-backend PR #59)</li>
<li>Fix build errors with GCC 16 and with OpenSSL 4 deprecations.
(freedv-backend PR #41, #73)</li>
</ul></li>
<li>Documentation:
<ul>
@ -1455,10 +1511,12 @@ sound cards. (PR #1567)</li>
<li>Windows audio thread timing improvements. (PR #1488)</li>
<li>Log when the sound server puts a PulseAudio stream on another
device. (PR #1591)</li>
<li>Log from the audio threads without blocking them. (freedv-backend PR
#60)</li>
</ul></li>
</ol>
<h2 data-number="19.2" id="v2.4.0-august-2026"><span
class="header-section-number">19.2</span> V2.4.0 August 2026</h2>
<h2 data-number="19.3" id="v2.4.0-august-2026"><span
class="header-section-number">19.3</span> V2.4.0 August 2026</h2>
<ol type="1">
<li>Bugfixes:
<ul>
@ -1569,8 +1627,8 @@ data-cites="barjac">@barjac</span>!</li>
#1435)</li>
</ul></li>
</ol>
<h2 data-number="19.3" id="earlier-than-v2.3.0"><span
class="header-section-number">19.3</span> Earlier than V2.3.0</h2>
<h2 data-number="19.4" id="earlier-than-v2.3.0"><span
class="header-section-number">19.4</span> Earlier than V2.3.0</h2>
<p>See <a
href="https://github.com/freedv/freedv-gui/blob/master/CHANGELOG_OLD.md">this</a>
for more information about changes in versions prior to 2.3.0.</p>

View File

@ -618,7 +618,7 @@ As the Tab is dragged into position a faint blue/gray image will show the positi
Tabs can be resized as required by hovering the cursor over the border and clicking and holding the left mouse button and dragging to required size.
By default, the tab layout is not saved. However, by enabling experimental features (see "Advanced/Developer Features"), experimental support for
By default, the tab layout is not saved. However, by enabling experimental features (see [Experimental Features](#experimental-features)), experimental support for
saving and restoring the tab layout will be enabled. This has not been well tested and may have hidden bugs or other issues.
![Multiple Panes](contrib/multiple_panes.png)
@ -947,7 +947,14 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
# Release Notes
## V2.4.1 TBD 2026
## V2.4.2 TBD 2026
1. Bugfixes:
* FreeDV Reporter: don't select the station under the mouse when the list gains focus without a click. (PR #1611)
2. Documentation:
* User manual: Update reference to Experimental Features section. (PR #1613)
## V2.4.1 October 2026
1. Bugfixes:
* Add logic to prevent FIFO sizes that are too small to allow TX thread to function. (PR #1474)
@ -1026,6 +1033,19 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
* Stop the radio recording budget at zero instead of wrapping it. (PR #1592)
* Windows: Fix issue preventing audio devices that don't support raw mode from starting. (PR #1594)
* PlotScalar: draw the trace when the plot is wider than its sample count. (PR #1597) - thanks @barjac!
* Linux/FreeDV Reporter: fix uninitialized value deciding whether a selection is honored. (PR #1606)
* Allow microphone and speaker devices below 16 kHz (such as Bluetooth headsets in call mode) with a warning instead of refusing to start. (PR #1608)
* FreeDV Reporter: fix possible crash when repeatedly connecting and disconnecting. (freedv-backend PR #44)
* FreeDV Reporter: fix exiting FreeDV taking up to 60 seconds when the server stalls setting up the secure connection; give up on it after 10 seconds instead. (freedv-backend PR #63)
* FreeDV Reporter: fix memory leak when FreeDV exits just as FreeDV Reporter connects. (freedv-backend PR #75)
* Recording: fix up to the last 100 ms of audio being lost when a recording stops, and log when audio has to be dropped. (freedv-backend PR #71, #72)
* Fix conversion of 16-bit audio to floating point going slightly past full scale. (freedv-backend PR #60)
* Fix buffer overruns when one RADE receive call decodes several frames and when resampling 8 kHz audio by large ratios. (freedv-backend PR #78)
* Fix the audio pipeline rebuilding its resampler when the sample rate is unchanged but not when it changes, and freeing the kept resampler twice. (freedv-backend PR #78)
* FreeDV Reporter: refuse a secure connection if TLS 1.2 or certificate hostname checking can't be enforced. (freedv-backend PR #78)
* macOS/FreeDV Reporter: fix endless loop and log spam when the connection closes while sending. (freedv-backend PR #78)
* Fix network and threading code continuing after a failed socket or semaphore setup, Linux semaphore waits ending early on a signal, and a macOS crash on an empty background task. (freedv-backend PR #78)
* Windows: fix exiting FreeDV taking 20 seconds or more while logging heavily. (freedv-backend PR #78)
2. Build system:
* Windows versions are now built with llvm-mingw 20260908 (PR #1489)
* Ccache support extended to third party dependencies. (PR #1498, #1505))
@ -1036,12 +1056,17 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
* Add unit tests for non-GUI code. (PR #1542)
* Add tests of whole transmissions through the TX/RX threads without sound cards. (PR #1567)
* Resolve build failure on OpenSUSE Tumbleweed. (PR #1577)
* Fix Windows build failures with newer llvm-mingw (clang/libc++) releases. (freedv-backend PR #51)
* Fix Windows build with older mingw-w64 headers that don't declare SetThreadDescription. (freedv-backend PR #60)
* macOS: fix RNNoise build failure with newer Xcode versions. (freedv-backend PR #59)
* Fix build errors with GCC 16 and with OpenSSL 4 deprecations. (freedv-backend PR #41, #73)
3. Documentation:
* Update documentation to reflect new repo URL. (PR #1569)
4. Other:
* Various GUI performance improvements. (PR #1481, #1521, #1524, #1527, #1531)
* Windows audio thread timing improvements. (PR #1488)
* Log when the sound server puts a PulseAudio stream on another device. (PR #1591)
* Log from the audio threads without blocking them. (freedv-backend PR #60)
## V2.4.0 August 2026

Binary file not shown.

View File

@ -1815,6 +1815,15 @@ void FreeDVReporterDialog::OnLeftClickTooltip(wxMouseEvent& event)
void FreeDVReporterDialog::OnSetFocus(wxFocusEvent& event)
{
// Only select the item under the mouse if the focus came from clicking
// on it, not from e.g. the window being brought to the front or a
// tooltip closing while the mouse happens to be over the list.
if (!wxGetMouseState().ButtonIsDown(wxMOUSE_BTN_ANY))
{
event.Skip();
return;
}
CallAfter([this]() {
const wxPoint pt = wxGetMousePosition();
int mouseX = pt.x - m_listSpots->GetScreenPosition().x;

View File

@ -527,7 +527,9 @@ class FreeDVReporterDialog : public wxFrame
};
bool isSelectionPossible_;
// Linux workaround to avoid inadvertent selections: set once the
// pointer has been over a row.
bool isSelectionPossible_ = false;
void createColumn_(int col, bool visible);
wxDataViewColumn* getColumnForModelColId_(unsigned int col);

View File

@ -4106,47 +4106,78 @@ bool MainFrame::validateSoundCardSetup(bool silent)
}
else
{
const int MIN_SAMPLE_RATE_ANALOG = 16000;
const int MIN_SAMPLE_RATE_RADIO = 8000;
int failedSampleRate = 0;
int expectedSampleRate = 0;
int expectedSampleRate1Out = (g_nSoundCards.load(std::memory_order_acquire) == 1 ? MIN_SAMPLE_RATE_ANALOG : MIN_SAMPLE_RATE_RADIO);
// Validate sample rates
if (wxGetApp().appConfiguration.audioConfiguration.soundCard1In.deviceName != "none" && wxGetApp().appConfiguration.audioConfiguration.soundCard1In.sampleRate < MIN_SAMPLE_RATE_RADIO)
// Below 8 kHz, FreeDV can't run at all. Mic and speaker devices
// below 16 kHz still work (audio is resampled), but they can't carry
// the upper half of RADE's 8 kHz audio bandwidth, so warn instead.
const int MIN_SAMPLE_RATE = 8000;
const int MIN_SAMPLE_RATE_ANALOG_RECOMMENDED = 16000;
auto& audioConfig = wxGetApp().appConfiguration.audioConfiguration;
bool oneSoundCard = g_nSoundCards.load(std::memory_order_acquire) == 1;
struct DeviceToCheck
{
failedDeviceName = wxGetApp().appConfiguration.audioConfiguration.soundCard1In.deviceName.get();
failedSampleRate = wxGetApp().appConfiguration.audioConfiguration.soundCard1In.sampleRate;
expectedSampleRate = MIN_SAMPLE_RATE_RADIO;
canRun = false;
wxString deviceName;
int sampleRate;
bool isAnalog;
};
DeviceToCheck devicesToCheck[] = {
{ audioConfig.soundCard1In.deviceName, audioConfig.soundCard1In.sampleRate, false },
{ audioConfig.soundCard1Out.deviceName, audioConfig.soundCard1Out.sampleRate, oneSoundCard },
{ audioConfig.soundCard2In.deviceName, audioConfig.soundCard2In.sampleRate, true },
{ audioConfig.soundCard2Out.deviceName, audioConfig.soundCard2Out.sampleRate, true },
};
std::vector<wxString> lowRateDeviceList;
wxString lowRateAnalogDevices;
for (auto& device : devicesToCheck)
{
const wxString& deviceName = device.deviceName;
if (deviceName == "none")
{
continue;
}
if (device.sampleRate < MIN_SAMPLE_RATE)
{
if (!silent)
{
wxMessageBox(wxString::Format(
"Your %s device is set to use a sample rate of %d, which is less than the minimum of %d. Please go to Tools->Audio Config... to check your settings.",
deviceName, device.sampleRate, MIN_SAMPLE_RATE), wxT("Sample Rate Too Low"), wxOK, this);
}
canRun = false;
break;
}
else if (device.isAnalog && device.sampleRate < MIN_SAMPLE_RATE_ANALOG_RECOMMENDED)
{
log_warn("%s is using a sample rate of %d; audio above %d Hz will be lost", (const char*)deviceName.ToUTF8(), device.sampleRate, device.sampleRate / 2);
wxString lowRateDeviceString = wxString::Format("%s (%d Hz)", deviceName, device.sampleRate);
bool found = false;
for (auto& str : lowRateDeviceList)
{
if (str == lowRateDeviceString)
{
found = true;
break;
}
}
if (!found) lowRateDeviceList.push_back(lowRateDeviceString);
}
}
else if (wxGetApp().appConfiguration.audioConfiguration.soundCard1Out.deviceName != "none" && wxGetApp().appConfiguration.audioConfiguration.soundCard1Out.sampleRate < expectedSampleRate1Out)
// Only warn once per session so that each Start doesn't bring this up again.
for (auto& str : lowRateDeviceList)
{
failedDeviceName = wxGetApp().appConfiguration.audioConfiguration.soundCard1Out.deviceName.get();
failedSampleRate = wxGetApp().appConfiguration.audioConfiguration.soundCard1Out.sampleRate;
expectedSampleRate = expectedSampleRate1Out;
canRun = false;
lowRateAnalogDevices += wxString::Format("\n%s", str);
}
else if (wxGetApp().appConfiguration.audioConfiguration.soundCard2In.deviceName != "none" && wxGetApp().appConfiguration.audioConfiguration.soundCard2In.sampleRate < MIN_SAMPLE_RATE_ANALOG)
{
failedDeviceName = wxGetApp().appConfiguration.audioConfiguration.soundCard2In.deviceName.get();
failedSampleRate = wxGetApp().appConfiguration.audioConfiguration.soundCard2In.sampleRate;
expectedSampleRate = MIN_SAMPLE_RATE_ANALOG;
canRun = false;
}
else if (wxGetApp().appConfiguration.audioConfiguration.soundCard2Out.deviceName != "none" && wxGetApp().appConfiguration.audioConfiguration.soundCard2Out.sampleRate < MIN_SAMPLE_RATE_ANALOG)
{
failedDeviceName = wxGetApp().appConfiguration.audioConfiguration.soundCard2Out.deviceName.get();
failedSampleRate = wxGetApp().appConfiguration.audioConfiguration.soundCard2Out.sampleRate;
expectedSampleRate = MIN_SAMPLE_RATE_ANALOG;
canRun = false;
}
if (!canRun && !silent)
static bool lowRateWarningShown = false;
if (canRun && !silent && !lowRateAnalogDevices.IsEmpty() && !lowRateWarningShown)
{
lowRateWarningShown = true;
wxMessageBox(wxString::Format(
"Your %s device is set to use a sample rate of %d, which is less than the minimum of %d. Please go to Tools->Audio Config... to check your settings.",
failedDeviceName, failedSampleRate, expectedSampleRate), wxT("Sample Rate Too Low"), wxOK, this);
"The following microphone/speaker devices are set to a sample rate below the recommended minimum of %d Hz:\n%s\n\nFreeDV will still work, but speech will sound muffled to you or to other stations, depending on which device it is. If your device supports a sample rate higher than 16 kHz, consider enabling it.",
MIN_SAMPLE_RATE_ANALOG_RECOMMENDED, lowRateAnalogDevices), wxT("Low Sample Rate"), wxOK | wxICON_WARNING, this);
}
}

View File

@ -147,15 +147,24 @@ bool recordsSamplesInOrder()
{
Recording recording;
// Pace things the way the audio device would so that this is about
// ordering rather than how much can be queued at once.
// Let each burst reach the file before queuing the next so that this is
// about ordering rather than how much can be queued at once (a fixed sleep
// isn't enough when the writer thread is starved, as on Windows runners).
std::vector<short> expected;
for (int block = 0; block < 100; block++)
{
auto samples = ramp(BLOCK_SIZE, block * BLOCK_SIZE);
expected.insert(expected.end(), samples.begin(), samples.end());
recording.record(samples);
if (block % 10 == 9) std::this_thread::sleep_for(std::chrono::milliseconds(5));
if (block % 10 == 9)
{
auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(5);
while (recording.numSamplesReported < (int)expected.size() &&
std::chrono::steady_clock::now() < deadline)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
}
return samplesAre(recording.finish(), expected);