fix: replaying a QSO used the voice keyer's level and overdrove the rig

A panadapter shot settles it: answering an S5 station, the replayed recording
goes out several times wider and taller than the station being answered — in WAV
as well as MP3, so this is not the encoder.

One setting served two sources that have nothing in common. A voice-keyer
message is a microphone at speaking distance and legitimately wants 195%; a QSO
recording is a receiver's line output, which is far hotter. The same 195% put it
into the transmitter flat out, ALC pinned, noise and voice alike.

The QSO playback now has its own level, defaulting to 100%. The voice keyer
keeps the setting it had, so nobody's F-key messages change.
This commit is contained in:
2026-07-31 21:32:55 +02:00
parent fddb3c45c4
commit ed67ed7fe3
5 changed files with 41 additions and 14 deletions
+8 -2
View File
@@ -1198,13 +1198,13 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
from_radio: string; to_radio: string; recording_device: string; listening_device: string;
qso_record: boolean; qso_dir: string; preroll_seconds: number;
ptt_method: 'none' | 'cat' | 'rts' | 'dtr'; ptt_port: string; format: 'wav' | 'mp3';
from_gain: number; mic_gain: number; tx_gain: number;
from_gain: number; mic_gain: number; tx_gain: number; qso_play_gain: number;
};
type AudioDev = { id: string; name: string; default: boolean };
const [audioCfg, setAudioCfg] = useState<AudioSettings>({
from_radio: '', to_radio: '', recording_device: '', listening_device: '',
qso_record: false, qso_dir: '', preroll_seconds: 8, ptt_method: 'none', ptt_port: '', format: 'wav',
from_gain: 100, mic_gain: 100, tx_gain: 100,
from_gain: 100, mic_gain: 100, tx_gain: 100, qso_play_gain: 100,
});
const [audioInputs, setAudioInputs] = useState<AudioDev[]>([]);
const [audioOutputs, setAudioOutputs] = useState<AudioDev[]>([]);
@@ -5118,6 +5118,12 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
onChange={(e) => { const v = parseInt(e.target.value, 10); setAudioField({ from_gain: v }); AudioApplyLevels(v, audioCfg.mic_gain); }} className="w-48 accent-primary" />
<span className="font-mono text-xs w-12 text-right">{audioCfg.from_gain}%</span>
</div>
<Label className="text-sm">{t('aud.qsoPlayLevel')}</Label>
<div className="flex items-center gap-2">
<input type="range" min={10} max={300} step={5} value={audioCfg.qso_play_gain}
onChange={(e) => setAudioField({ qso_play_gain: parseInt(e.target.value, 10) })} className="w-48 accent-primary" />
<span className="font-mono text-xs w-12 text-right">{audioCfg.qso_play_gain}%</span>
</div>
<Label className="text-sm">{t('aud.micLevel')}</Label>
<div className="flex items-center gap-2">
<input type="range" min={10} max={300} step={5} value={audioCfg.mic_gain}