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

Method onBinaryMessage

src/core/TciServer.cpp:882–1061  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

880// ── Binary message handler (TX audio from TCI client) ───────────────────
881
882void TciServer::onBinaryMessage(const QByteArray& data)
883{
884 if (!m_audio) return;
885 if (data.size() < static_cast<int>(sizeof(TciAudioHeader))) return;
886
887 // Parse header
888 TciAudioHeader hdr;
889 std::memcpy(&hdr, data.constData(), sizeof(hdr));
890
891 // Only accept TX_AUDIO_STREAM (type 2)
892 if (hdr.type != 2) return;
893
894 const int payloadBytes = data.size() - static_cast<int>(sizeof(TciAudioHeader));
895 if (payloadBytes <= 0) return;
896
897 const char* payload = data.constData() + sizeof(TciAudioHeader);
898
899 // ── Convert TX audio to float32 stereo ─────────────────────────────────
900 // WSJT-X channels field is garbage (FIFO reuse). readAudioData() writes
901 // hdr.length floats to data[0..length-1]. Take the first hdr.length floats.
902 QByteArray pcm;
903
904 if (hdr.format == 3) {
905 int validFloats = static_cast<int>(hdr.length);
906 int availFloats = payloadBytes / static_cast<int>(sizeof(float));
907 if (validFloats > availFloats) validFloats = availFloats;
908 if (validFloats <= 0) return;
909
910 pcm = QByteArray(payload,
911 validFloats * static_cast<int>(sizeof(float)));
912 } else if (hdr.format == 0) {
913 int validSamples = static_cast<int>(hdr.length);
914 int availSamples = payloadBytes / static_cast<int>(sizeof(qint16));
915 if (validSamples > availSamples) validSamples = availSamples;
916 if (validSamples <= 0) return;
917
918 auto* src = reinterpret_cast<const qint16*>(payload);
919 pcm.resize(validSamples * static_cast<int>(sizeof(float)));
920 auto* dst = reinterpret_cast<float*>(pcm.data());
921 for (int i = 0; i < validSamples; ++i)
922 dst[i] = src[i] / 32768.0f;
923 }
924
925 if (pcm.isEmpty()) return;
926
927 int inputFramesSrcRate = 0; // input frames at the client-declared rate (#3914)
928 bool duplicatedStereo = false;
929
930 // ─── TX resampling: client-declared rate → 24kHz (radio native DAX) ──
931 // Resample from the rate the client declared in THIS frame (hdr.sampleRate),
932 // not a hardcoded 48k. WSJT-X sends 48 kHz — the common path, unchanged — but
933 // a client that negotiated 8/12/24 kHz (audio_samplerate) sends at that rate
934 // and must be resampled from it, or every tone is mis-pitched and digital
935 // decodes fail (#3306). Rebuild the per-session resampler only if the
936 // declared rate changes (rare, mid-stream); a 24 kHz client gets a 1:1
937 // resampler so the mono/stereo canonicalization below still runs.
938 {
939 const int declaredRate = static_cast<int>(hdr.sampleRate);

Callers

nothing calls this directly

Calls 6

srcRateMethod · 0.80
processStereoToStereoMethod · 0.80
processMonoToStereoMethod · 0.80
sizeMethod · 0.45
dataMethod · 0.45
isEmptyMethod · 0.45

Tested by

no test coverage detected