| 141 | } |
| 142 | |
| 143 | void MainWindow::wireDspApplets() |
| 144 | { |
| 145 | // ── P/CW applet: mic meters + ALC meter + model ──────────────────────── |
| 146 | // Suppress radio CODEC meters when mic_selection=PC (they just show noise). |
| 147 | // Client-side metering handles PC mic display below. |
| 148 | // Compression gauge: full 20fps meter rate, gated on actual radio TX + PROC. |
| 149 | { |
| 150 | connect(&m_radioModel.meterModel(), &MeterModel::micMetersChanged, |
| 151 | this, [this](float micLevel, float compLevel, float micPeak, float compPeak) { |
| 152 | // Mic level: hardware mic uses radio meters, PC uses client-side |
| 153 | if (m_radioModel.transmitModel().micSelection() != "PC") |
| 154 | m_appletPanel->phoneCwApplet()->updateMeters(micLevel, compLevel, micPeak, 0.0f); |
| 155 | |
| 156 | // Compression has no useful meaning in RX; FLEX-8000 radios can |
| 157 | // publish quiescent TX-chain meters there that look fully pegged. |
| 158 | { |
| 159 | const auto& tx = m_radioModel.transmitModel(); |
| 160 | const bool showCompression = |
| 161 | m_radioModel.isRadioTransmitting() && tx.speechProcessorEnable(); |
| 162 | m_appletPanel->phoneCwApplet()->updateCompression( |
| 163 | showCompression ? compPeak : 0.0f); |
| 164 | } |
| 165 | }); |
| 166 | } |
| 167 | connect(&m_radioModel.meterModel(), &MeterModel::swAlcChanged, |
| 168 | this, [this](float alc) { |
| 169 | // FLEX-8000 TX-chain meters can publish quiescent RX values near 0 dBFS. |
| 170 | // Only show SW ALC while the radio interlock says RF is actually keyed. |
| 171 | m_appletPanel->phoneCwApplet()->updateAlc( |
| 172 | m_radioModel.isRadioTransmitting() ? alc : -20.0f); |
| 173 | }); |
| 174 | // Client-side PC mic metering — radio CODEC meters only see hardware mics. |
| 175 | // Apply VU-style ballistics: fast attack, slow decay (~20 dB/sec). |
| 176 | { |
| 177 | auto heldLevel = std::make_shared<float>(-150.0f); |
| 178 | auto heldPeak = std::make_shared<float>(-150.0f); |
| 179 | connect(m_audio, &AudioEngine::pcMicLevelChanged, |
| 180 | this, [this, heldLevel, heldPeak](float peakDb, float avgDb) { |
| 181 | if (m_radioModel.transmitModel().micSelection() != "PC" && !m_audio->isRadeMode()) return; |
| 182 | constexpr float kDecayPerUpdate = 1.0f; // ~20 dB/sec at 20 updates/sec |
| 183 | // Level: fast attack, slow decay |
| 184 | if (avgDb > *heldLevel) |
| 185 | *heldLevel = avgDb; |
| 186 | else |
| 187 | *heldLevel = qMax(avgDb, *heldLevel - kDecayPerUpdate); |
| 188 | // Peak: fast attack, slower decay |
| 189 | if (peakDb > *heldPeak) |
| 190 | *heldPeak = peakDb; |
| 191 | else |
| 192 | *heldPeak = qMax(*heldLevel, *heldPeak - kDecayPerUpdate * 0.5f); |
| 193 | m_appletPanel->phoneCwApplet()->updateMeters(*heldLevel, 0.0f, *heldPeak, 0.0f); |
| 194 | }); |
| 195 | } |
| 196 | m_appletPanel->phoneCwApplet()->setTransmitModel(&m_radioModel.transmitModel()); |
| 197 | |
| 198 | |
| 199 | |
| 200 | // ── PHNE applet: VOX + CW controls ────────────────────────────────────── |
nothing calls this directly
no test coverage detected