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

Method AudioEngine

src/core/AudioEngine.cpp:1038–1782  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1036}
1037
1038AudioEngine::AudioEngine(QObject* parent)
1039 : QObject(parent)
1040 , m_clientEqRx(std::make_unique<ClientEq>())
1041 , m_clientEqTx(std::make_unique<ClientEq>())
1042 , m_clientCompTx(std::make_unique<ClientComp>())
1043 , m_clientCompRx(std::make_unique<ClientComp>())
1044 , m_clientGateTx(std::make_unique<ClientGate>())
1045 , m_clientGateRx(std::make_unique<ClientGate>())
1046 , m_clientDeEssTx(std::make_unique<ClientDeEss>())
1047 , m_clientDeEssRx(std::make_unique<ClientDeEss>())
1048 , m_clientTubeTx(std::make_unique<ClientTube>())
1049 , m_clientTubeRx(std::make_unique<ClientTube>())
1050 , m_clientPuduTx(std::make_unique<ClientPudu>())
1051 , m_clientPuduRx(std::make_unique<ClientPudu>())
1052 , m_clientReverbTx(std::make_unique<ClientReverb>())
1053 , m_clientFinalLimiterTx(std::make_unique<ClientFinalLimiter>())
1054 , m_clientTxTestTone(std::make_unique<ClientTxTestTone>())
1055 , m_cwSidetone(std::make_unique<CwSidetoneGenerator>(48000))
1056 , m_cwRecordSidetone(std::make_unique<CwSidetoneGenerator>(DEFAULT_SAMPLE_RATE))
1057 , m_clientQuindarTone(std::make_unique<ClientQuindarTone>())
1058{
1059 // Recorder-sidetone generator: always enabled at a fixed, audible level and
1060 // centre pan so a Client-Side QSO recording captures the operator's sent
1061 // CW/CWX regardless of the audible monitor's volume/enable state (#2539).
1062 // Its pitch is mirrored from the audible generator each TX block.
1063 m_cwRecordSidetone->setEnabled(true);
1064 m_cwRecordSidetone->setVolume(0.5f);
1065 m_cwRecordSidetone->setPan(0.5f);
1066 // TX-side CW decode mirror (#2417). Plug the sidetone generator's
1067 // per-block tap into a downsampler + signal emitter; gated on the
1068 // m_cwDecodeTxTapEnabled atomic so MainWindow can flip TX-decode on
1069 // and off without rebuilding any audio plumbing. Runs on the
1070 // sidetone audio thread.
1071 m_cwSidetone->setSampleTap(
1072 [this](const float* mono, int frames, int sampleRateHz) {
1073 if (!m_cwDecodeTxTapEnabled.load(std::memory_order_relaxed))
1074 return;
1075 if (frames <= 0 || sampleRateHz <= 0) return;
1076 // CwDecoder::feedAudio expects 24 kHz stereo float32 — the
1077 // same shape PanadapterStream::audioDataReady() emits on
1078 // the RX side. Decimate 48→24 by averaging consecutive
1079 // pairs; the sidetone is a single sine well below 12 kHz
1080 // so the cheap two-tap LPF is sufficient for ggmorse. For
1081 // sample rates that are not an integer multiple of 24 kHz
1082 // (rare — only when the device forced a 44.1 kHz negotiation),
1083 // fall back to nearest-neighbour stepping.
1084 constexpr int kTargetHz = 24000;
1085 QByteArray buf;
1086 if (sampleRateHz == 48000) {
1087 const int outFrames = frames / 2;
1088 if (outFrames <= 0) return;
1089 buf.resize(outFrames * 2 * static_cast<int>(sizeof(float)));
1090 auto* out = reinterpret_cast<float*>(buf.data());
1091 for (int i = 0; i < outFrames; ++i) {
1092 const float s = 0.5f * (mono[2 * i] + mono[2 * i + 1]);
1093 out[2 * i] = s; // L
1094 out[2 * i + 1] = s; // R
1095 }

Callers

nothing calls this directly

Calls 15

logStartupEnvironmentFunction · 0.85
logNr2WisdomSummaryFunction · 0.85
queuedAudioBytesFunction · 0.85
rawEquivalentAudioBytesFunction · 0.85
moveFunction · 0.85
alignedStereoFloatBytesFunction · 0.85
audioBytesToMsFunction · 0.85
setPanMethod · 0.80
setSampleTapMethod · 0.80
idMethod · 0.80

Tested by

no test coverage detected