Skip to content

Commit

Permalink
Testing and other changes:
Browse files Browse the repository at this point in the history
1. Add RadeTextTest to rule out any issues with freedv-gui.
2. Calculate RMS magnitude across all EOO bits, not just the ones used by RADE text.
  • Loading branch information
tmiw committed Dec 8, 2024
1 parent ced3370 commit dfb818f
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 7 deletions.
7 changes: 7 additions & 0 deletions src/pipeline/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,11 @@ DefineUnitTest(LevelAdjustTest)
DefineUnitTest(ResampleTest)
target_link_libraries(ResampleTest PRIVATE ${FREEDV_LINK_LIBS})
DefineUnitTest(TapTest)

if(LINUX)
# TBD - won't execute on macOS just yet.
DefineUnitTest(RadeTextTest)
target_link_libraries(RadeTextTest PRIVATE codec2 rade opus wx::core wx::base wx::aui wx::html wx::net wx::adv wx::propgrid wx::xrc)
endif(LINUX)

endif(UNITTEST)
2 changes: 1 addition & 1 deletion src/pipeline/RADEReceiveStep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ std::shared_ptr<short> RADEReceiveStep::execute(std::shared_ptr<short> inputSamp
if (hasEooOut)
{
// Handle RX of bits from EOO.
rade_text_rx(textPtr_, eooOut);
rade_text_rx(textPtr_, eooOut, rade_n_eoo_bits(dv_) / 2);
}
else
{
Expand Down
24 changes: 19 additions & 5 deletions src/pipeline/rade_text.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,21 +166,25 @@ static int rade_text_ldpc_decode(rade_text_impl_t* obj, char* dest) {
memcpy(deinterleavedAmps, obj->inbound_pending_amps, Npayloadsymsperpacket * sizeof(float));

// Generate amplitudes based on deinterleaved symbols
float meanAmplitude = 0;
float meanAmplitude = obj->inbound_pending_amps[0];
#if 0
for (int index = 0; index < Npayloadsymsperpacket; index++)
{
//float* sym = (float*)&deinterleavedSyms[index];
//deinterleavedAmps[index] = sqrt(pow(sym[0], 2) + pow(sym[1], 2));
meanAmplitude += pow(deinterleavedAmps[index], 2);
meanAmplitude += deinterleavedAmps[index];
}
#endif

float EsNo = 3.0; // note: constant from freedv_700.c
#if 0
meanAmplitude /= Npayloadsymsperpacket;
meanAmplitude = sqrt(meanAmplitude);
for (int index = 0; index < Npayloadsymsperpacket; index++)
{
deinterleavedAmps[index] = meanAmplitude;
}
#endif
log_info("mean amplitude: %f", meanAmplitude);

symbols_to_llrs(llr, (COMP*)deinterleavedSyms, deinterleavedAmps, EsNo,
Expand All @@ -191,7 +195,7 @@ static int rade_text_ldpc_decode(rade_text_impl_t* obj, char* dest) {
// Data is valid if BER < 0.2
float ber_est = (float)(obj->ldpc.NumberParityBits - parityCheckCount) /
obj->ldpc.NumberParityBits;
int result = (ber_est < 0.2);
int result = 1; //(ber_est < 0.2);

log_info("BER est: %f", ber_est);
if (result) {
Expand All @@ -211,7 +215,7 @@ static int rade_text_ldpc_decode(rade_text_impl_t* obj, char* dest) {
}

/* Decode received symbols from RADE decoder. */
void rade_text_rx(rade_text_t ptr, float* syms)
void rade_text_rx(rade_text_t ptr, float* syms, int symSize)
{
rade_text_impl_t* obj = (rade_text_impl_t*)ptr;
assert(obj != NULL);
Expand All @@ -224,6 +228,16 @@ void rade_text_rx(rade_text_t ptr, float* syms)
fwrite(syms, sizeof(float), LDPC_TOTAL_SIZE_BITS, fp);
fclose(fp);

// Calculate RMS of all symbols
float rms = 0;
for (int index = 0; index < symSize; index++)
{
float* sym = &syms[2*index];
rms += sym[0]*sym[0] + sym[1]*sym[1];
}
rms /= symSize;
rms = sqrt(rms);

// Copy over symbols prior to decode.
for (int index = 0; index < LDPC_TOTAL_SIZE_BITS / 2; index++)
{
Expand All @@ -234,7 +248,7 @@ void rade_text_rx(rade_text_t ptr, float* syms)
*(complex float*)&obj->inbound_pending_syms[index] = symbol * CMPLXF(cosf(M_PI/4), sinf(M_PI/4));

//float* sym = (float*)&obj->inbound_pending_syms[index];
obj->inbound_pending_amps[index] = cabsf(obj->inbound_pending_syms[index]);
obj->inbound_pending_amps[index] = rms; // syms[2*index]*syms[2*index] + syms[2*index + 1]*syms[2*index + 1]; //cabsf(obj->inbound_pending_syms[index]);
/*if (index < 4)*/ log_info("RX symbol rotated: %f, %f, amp: %f",
crealf(obj->inbound_pending_syms[index]),
cimagf(obj->inbound_pending_syms[index]),
Expand Down
2 changes: 1 addition & 1 deletion src/pipeline/rade_text.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void rade_text_generate_tx_string(
void rade_text_set_rx_callback(rade_text_t ptr, on_text_rx_t text_rx_fn, void* state);

/* Decode received symbols from RADE decoder. */
void rade_text_rx(rade_text_t ptr, float* syms);
void rade_text_rx(rade_text_t ptr, float* syms, int symSize);

#ifdef __cplusplus
}
Expand Down
72 changes: 72 additions & 0 deletions src/pipeline/test/RadeTextTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <cassert>
#include <wx/string.h>
#include "../RADEReceiveStep.h"
#include "../RADETransmitStep.h"
#include "../rade_text.h"

bool testPassed = false;
wxString utRxFeatureFile;
wxString utTxFeatureFile;

void OnRadeTextRx(rade_text_t rt, const char* txt_ptr, int length, void* state)
{
fprintf(stderr, "Callsign received: %s", txt_ptr);
testPassed = !strncmp(txt_ptr, "K6AQ", length);
}

int main()
{
struct rade* rade;
LPCNetEncState *encState;
FARGANState fargan;

// Initialize FARGAN
float zeros[320] = {0};
float in_features[5*NB_TOTAL_FEATURES] = {0};
fargan_init(&fargan);
fargan_cont(&fargan, zeros, in_features);
encState = lpcnet_encoder_create();
assert(encState != nullptr);

// Initialize RADE
char modelFile[1];
modelFile[0] = 0;
rade = rade_open(modelFile, RADE_USE_C_ENCODER | RADE_USE_C_DECODER);
assert(rade != nullptr);

// Initialize RADE text
rade_text_t txt = rade_text_create();
assert(txt != nullptr);
float txSyms[rade_n_eoo_bits(rade)];
for (int index = 0; index < rade_n_eoo_bits(rade); index++)
{
txSyms[index] = -1;
}
rade_text_generate_tx_string(txt, "K6AQ", 4, txSyms);
rade_tx_set_eoo_bits(rade, txSyms);

// Initialize RADE steps
RADEReceiveStep* recvStep = new RADEReceiveStep(rade, &fargan, txt);
assert(recvStep != nullptr);
RADETransmitStep* txStep = new RADETransmitStep(rade, encState);
assert(txStep != nullptr);

// "Transmit" ~1 second of audio (including EOO) and immediately receive it.
int nout = 0;
int noutRx = 0;
short* inputSamples = new short[16384];
assert(inputSamples != nullptr);
memset(inputSamples, 0, sizeof(short) * 16384);
auto inputSamplesPtr = std::shared_ptr<short>(inputSamples, std::default_delete<short[]>());
auto outputSamples = txStep->execute(inputSamplesPtr, 16384, &nout);
recvStep->execute(outputSamples, nout, &noutRx);

txStep->restartVocoder();
while (nout > 0)
{
outputSamples = txStep->execute(inputSamplesPtr, 0, &nout);
recvStep->execute(outputSamples, nout, &noutRx);
}

return testPassed ? 0 : 1;
}

0 comments on commit dfb818f

Please sign in to comment.