fix(cw): a drifting tone wiped the record instead of filling it
The record could go from a screenful of text to less, and then to nothing at all, while
decoding was still running. The cause is dropBufferedAudio(), which runs on every change
of shift - and the shift tracks the detected tone, which drifts across a pass.
The live window is the only route into the archive: audio gets there by being pushed out
by newer audio. Clearing the window therefore did not merely discard 20 s, it reset the
progress towards ever archiving anything. Modelled at 18 WPM, a drift every 20 s meant
five minutes of listening archived not one character, however long the operator waited -
the window was always wiped before the first sample could be evicted. With the record
still concatenating the live decode at the time, each wipe also cut the visible
transcript short, which is the text going backwards and then never accumulating.
Retiring the window instead of dropping it fixes both. Those samples cannot stay - one
spectrogram over two shift amounts smears the tone - but they were shifted consistently
and they are complete, so they decode fine on their own. They are queued and archived by
the normal path, keeping dropBufferedAudio() non-suspending: both callers sit on the
synchronous capture path, and decoding there would put an inference inside the tone
scan. Modelled over 300 s, a drift every 5 s goes from 0 characters archived to 449.
An earlier attempt at this - keeping archiveSize instead of zeroing it - was wrong and
the probe rejected it: with the window wiped before it ever overflowed, that buffer was
empty, so preserving it preserved nothing.
The queue is synchronised (written from capture, drained from capture and flush) and
capped at four windows, dropping the oldest when full: a tone drifting on every
detection scan would otherwise queue faster than the decoder can drain.
Also from an audit of the previous two commits:
- The copy button was gated on the record, which is empty for the opening half-minute
while the first batch accumulates. That greyed out the one control that rescues the
text over exactly the short exchange most likely to be lost. It now copies the live
window too, and the empty state says which surface updates sooner.
- cw_copy, cw_copied, cw_record_label and cw_record_empty were missing from values-id,
values-in and values-tr, which carry the full UI strings, so those users saw English.
- Dropped a KDoc block left dangling by 8445c170, which had removed the constant it
documented.
This commit is contained in:
1 parent
3810e76ea2
commit
cc4f156c83
7 files changed
+107
-17
No files matched your search
@@ -73,13 +73,6 @@ import com.rtbishop.look4sat.core.domain.repository.IContainerProvider
|
||||
import com.rtbishop.look4sat.core.presentation.R as CoreR
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Scroll slack, in pixels, within which the transcript counts as being at the bottom.
|
||||
*
|
||||
* Not zero: an animated scroll settles a pixel or two short of the maximum, and an exact
|
||||
* comparison would drop out of follow-mode the moment it did.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Full-page CW decoder backed by DeepCW.
|
||||
*
|
||||
@@ -182,18 +175,24 @@ fun CwDecodeScreen() {
|
||||
.weight(1f)
|
||||
.padding(start = 12.dp)
|
||||
)
|
||||
// Copy the record out. The decoder is built fresh every time this screen is opened,
|
||||
// so leaving the screen loses the transcript - and until now there was no way at all
|
||||
// to get the text off it. An operator who has just copied a callsign by ear should not
|
||||
// have to transcribe it a second time by hand.
|
||||
// Copy everything decoded so far. The decoder is built fresh every time this screen
|
||||
// is opened, so leaving loses the transcript, and until now there was no way at all
|
||||
// to get the text off it: an operator who had just copied a call sign by ear had to
|
||||
// transcribe it a second time by hand.
|
||||
//
|
||||
// Includes the live window, not just the record. The record only holds archived text,
|
||||
// which needs the window to fill and then a batch to accumulate, so for the opening
|
||||
// half-minute it is empty - and gating the button on it left the one control that
|
||||
// rescues the text greyed out over exactly the short exchange most likely to be lost.
|
||||
val copyable = (historyText + decodedText).trim()
|
||||
IconButton(
|
||||
onClick = {
|
||||
if (historyText.isNotEmpty()) {
|
||||
clipboard.setText(AnnotatedString(historyText))
|
||||
if (copyable.isNotEmpty()) {
|
||||
clipboard.setText(AnnotatedString(copyable))
|
||||
showToast(copiedMessage)
|
||||
}
|
||||
},
|
||||
enabled = historyText.isNotEmpty()
|
||||
enabled = copyable.isNotEmpty()
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(CoreR.drawable.ic_save),
|
||||
|
||||
@@ -14,4 +14,8 @@
|
||||
<string name="cw_waterfall_shifted">nada %1$d hertz, dipindahkan ke rentang dekode</string>
|
||||
<string name="cw_waterfall_outside">nada %1$d hertz, di luar rentang dekode</string>
|
||||
<string name="cw_waterfall_inside">nada %1$d hertz</string>
|
||||
<string name="cw_copy">Salin catatan</string>
|
||||
<string name="cw_copied">Catatan disalin</string>
|
||||
<string name="cw_record_label">Catatan</string>
|
||||
<string name="cw_record_empty">Teks muncul di sini setelah satu batch audio didekode. Baris di atas lebih cepat diperbarui. Salin sebelum keluar: catatan tidak disimpan.</string>
|
||||
</resources>
|
||||
@@ -14,4 +14,8 @@
|
||||
<string name="cw_waterfall_shifted">nada %1$d hertz, dipindahkan ke rentang dekode</string>
|
||||
<string name="cw_waterfall_outside">nada %1$d hertz, di luar rentang dekode</string>
|
||||
<string name="cw_waterfall_inside">nada %1$d hertz</string>
|
||||
<string name="cw_copy">Salin catatan</string>
|
||||
<string name="cw_copied">Catatan disalin</string>
|
||||
<string name="cw_record_label">Catatan</string>
|
||||
<string name="cw_record_empty">Teks muncul di sini setelah satu batch audio didekode. Baris di atas lebih cepat diperbarui. Salin sebelum keluar: catatan tidak disimpan.</string>
|
||||
</resources>
|
||||
@@ -14,4 +14,8 @@
|
||||
<string name="cw_waterfall_shifted">ton %1$d hertz, kod çözme aralığına taşındı</string>
|
||||
<string name="cw_waterfall_outside">ton %1$d hertz, kod çözme aralığının dışında</string>
|
||||
<string name="cw_waterfall_inside">ton %1$d hertz</string>
|
||||
<string name="cw_copy">Kaydı kopyala</string>
|
||||
<string name="cw_copied">Kayıt kopyalandı</string>
|
||||
<string name="cw_record_label">Kayıt</string>
|
||||
<string name="cw_record_empty">Bir ses grubu çözüldükten sonra metin buraya düşer. Üstteki satır daha erken güncellenir. Çıkmadan önce kopyalayın: kayıt saklanmaz.</string>
|
||||
</resources>
|
||||
@@ -17,5 +17,5 @@
|
||||
<string name="cw_copy">复制记录</string>
|
||||
<string name="cw_copied">记录已复制</string>
|
||||
<string name="cw_record_label">记录</string>
|
||||
<string name="cw_record_empty">解码文字会汇集到这里。离开本页前请复制:记录不会被存下来。</string>
|
||||
<string name="cw_record_empty">一批音频解码完成后文字会落到这里,上面那行更新更早。离开本页前请复制:记录不会被存下来。</string>
|
||||
</resources>
|
||||
@@ -17,5 +17,5 @@
|
||||
<string name="cw_copy">Copy the record</string>
|
||||
<string name="cw_copied">Record copied</string>
|
||||
<string name="cw_record_label">Record</string>
|
||||
<string name="cw_record_empty">Decoded text collects here. Copy it before leaving this screen: the record is not stored.</string>
|
||||
<string name="cw_record_empty">Text lands here once a batch of audio has been decoded. The line above updates sooner. Copy before leaving: the record is not stored.</string>
|
||||
</resources>
|
||||
Reference in new issue
Block a user