MCPcopy Create free account
hub / github.com/aethersdr/AetherSDR / startTxStream

Method startTxStream

src/core/AudioEngine.cpp:5738–6092  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

5736// ─── TX stream ────────────────────────────────────────────────────────────────
5737
5738bool AudioEngine::startTxStream(const QHostAddress& radioAddress, quint16 radioPort)
5739{
5740 if (m_audioSource) return true; // already running
5741
5742 // WASAPI silent-open recovery (#2929). If the previous open was driven
5743 // by the silence watchdog, m_txForceMonoOnNextOpen is true; consume it
5744 // here. A fresh (non-watchdog) start re-enables the one-shot retry budget.
5745 const bool isWatchdogRetry = m_txForceMonoOnNextOpen;
5746 m_txForceMonoOnNextOpen = false;
5747 if (!isWatchdogRetry) {
5748 m_txSilenceRetryDone = false;
5749 }
5750 m_txReceivedAnyBytes = false;
5751
5752 m_txAddress = radioAddress;
5753 m_txPort = radioPort;
5754 m_txPacketCount = 0;
5755 m_txAccumulator.clear();
5756 m_txMicChannelState.reset();
5757 m_lastTxMicChannelLog.invalidate();
5758
5759 // TX mic capture uses Int16 — we convert to float32 after capture.
5760 // (makeFormat() returns Float for the RX sink, but mic hardware is Int16.)
5761 QAudioFormat fmt;
5762 fmt.setSampleRate(DEFAULT_SAMPLE_RATE);
5763 fmt.setChannelCount(2);
5764 fmt.setSampleFormat(QAudioFormat::Int16);
5765 QAudioDevice dev = QMediaDevices::defaultAudioInput();
5766 bool txFallbackOccurred = false;
5767 QStringList txFallbackReasons;
5768 QStringList txFormatAttempts;
5769 const auto noteTxFallback = [&txFallbackOccurred, &txFallbackReasons](const QString& reason) {
5770 txFallbackOccurred = true;
5771 if (!reason.isEmpty() && !txFallbackReasons.contains(reason)) {
5772 txFallbackReasons << reason;
5773 }
5774 };
5775 const auto noteTxAttempt = [&txFormatAttempts](const QAudioFormat& format) {
5776 const QString attempt = formatAudioAttempt(format.sampleRate(),
5777 format.channelCount(),
5778 format.sampleFormat());
5779 if (!txFormatAttempts.contains(attempt)) {
5780 txFormatAttempts << attempt;
5781 }
5782 };
5783 if (!m_inputDevice.isNull()) {
5784 const auto inputs = QMediaDevices::audioInputs();
5785 if (devicePresent(inputs, m_inputDevice)) {
5786 dev = m_inputDevice;
5787 } else {
5788 qCWarning(lcAudio) << "AudioEngine: saved input device is unavailable, using the system default input instead";
5789 noteTxFallback(QStringLiteral("saved input unavailable -> system default"));
5790 m_inputDevice = QAudioDevice{};
5791 }
5792 }
5793
5794 if (dev.isNull()) {
5795 qCWarning(lcAudio) << "AudioEngine: no audio input device available";

Callers 3

audioStartTxMethod · 0.80

Calls 15

formatAudioAttemptFunction · 0.85
formatLadderFunction · 0.85
hostTargetOsFunction · 0.85
logAudioOpenFailureFunction · 0.85
audioErrorNameFunction · 0.85
logTxSourceFunction · 0.85
invalidateMethod · 0.80
setSampleRateMethod · 0.80
containsMethod · 0.80
isNullMethod · 0.80
idMethod · 0.80

Tested by

no test coverage detected