Initial implementation of RX feature capture.

pull/776/head
Mooneer Salem 2024-11-24 23:29:46 -08:00
parent 44b33f84ec
commit 1fa572edc9
3 changed files with 56 additions and 9 deletions

View File

@ -191,6 +191,7 @@ wxConfigBase *pConfig = NULL;
// Unit test management
wxString testName;
wxString utFreeDVMode;
wxString utRxFile;
// WxWidgets - initialize the application
@ -327,18 +328,36 @@ void MainApp::UnitTest_()
}
else
{
// Receive for 60 seconds
auto sync = 0;
for (int i = 0; i < 60*10; i++)
if (utRxFile != "")
{
std::this_thread::sleep_for(100ms);
auto newSync = freedvInterface.getSync();
if (newSync != sync)
// Receive until file has finished playing
SF_INFO sfInfo;
sfInfo.format = 0;
g_sfPlayFileFromRadio = sf_open((const char*)utRxFile.ToUTF8(), SFM_READ, &sfInfo);
g_sfFs = sfInfo.samplerate;
g_loopPlayFileFromRadio = false;
g_playFileFromRadio = true;
while (g_playFileFromRadio)
{
log_info("Sync changed from %d to %d", sync, newSync);
sync = newSync;
std::this_thread::sleep_for(20ms);
}
}
}
else
{
// Receive for 60 seconds
auto sync = 0;
for (int i = 0; i < 60*10; i++)
{
std::this_thread::sleep_for(100ms);
auto newSync = freedvInterface.getSync();
if (newSync != sync)
{
log_info("Sync changed from %d to %d", sync, newSync);
sync = newSync;
}
}
}
}
// Fire event to stop FreeDV
@ -369,6 +388,7 @@ void MainApp::OnInitCmdLine(wxCmdLineParser& parser)
parser.AddOption("f", "config", "Use different configuration file instead of the default.");
parser.AddOption("ut", "unit_test", "Execute FreeDV in unit test mode.");
parser.AddOption("utmode", wxEmptyString, "Switch FreeDV to the given mode before UT execution.");
parser.AddOption("rxfile", wxEmptyString, "In UT mode, pipes given WAV file through receive pipeline.");
}
bool MainApp::OnCmdLineParsed(wxCmdLineParser& parser)
@ -403,6 +423,11 @@ bool MainApp::OnCmdLineParsed(wxCmdLineParser& parser)
{
log_info("Using mode %s for tests", (const char*)utFreeDVMode.ToUTF8());
}
if (parser.Found("rxfile", &utRxFile))
{
log_info("Piping %s through RX pipeline", (const char*)utRxFile.ToUTF8());
}
}
return true;

View File

@ -25,11 +25,14 @@
#include "../defines.h"
#include "lpcnet.h" // from Opus source tree
extern wxString utRxFile;
RADEReceiveStep::RADEReceiveStep(struct rade* dv, FARGANState* fargan)
: dv_(dv)
, fargan_(fargan)
, inputSampleFifo_(nullptr)
, outputSampleFifo_(nullptr)
, featuresFile_(nullptr)
{
// Set FIFO to be 2x the number of samples per run so we don't lose anything.
inputSampleFifo_ = codec2_fifo_create(rade_nin_max(dv_) * 2);
@ -38,10 +41,21 @@ RADEReceiveStep::RADEReceiveStep(struct rade* dv, FARGANState* fargan)
// Enough for one second of audio. Probably way overkill.
outputSampleFifo_ = codec2_fifo_create(16000);
assert(outputSampleFifo_ != nullptr);
if (utRxFile != "")
{
featuresFile_ = fopen("features_out.f32", "wb");
assert(featuresFile_ != nullptr);
}
}
RADEReceiveStep::~RADEReceiveStep()
{
if (featuresFile_ != nullptr)
{
fclose(featuresFile_);
}
if (inputSampleFifo_ != nullptr)
{
codec2_fifo_free(inputSampleFifo_);
@ -93,6 +107,11 @@ std::shared_ptr<short> RADEReceiveStep::execute(std::shared_ptr<short> inputSamp
// RADE processing (input signal->features).
nout = rade_rx(dv_, features_out, input_buf_cplx);
if (featuresFile_)
{
fwrite(features_out, sizeof(float), nout, featuresFile_);
}
for (int i = 0; i < nout; i++)
{
pendingFeatures_.push_back(features_out[i]);

View File

@ -23,6 +23,7 @@
#ifndef AUDIO_PIPELINE__RADE_RECEIVE_STEP_H
#define AUDIO_PIPELINE__RADE_RECEIVE_STEP_H
#include <cstdio>
#include <vector>
#include "IPipelineStep.h"
#include "../freedv_interface.h"
@ -53,6 +54,8 @@ private:
struct FIFO* inputSampleFifo_;
struct FIFO* outputSampleFifo_;
std::vector<float> pendingFeatures_;
FILE* featuresFile_;
};
#endif // AUDIO_PIPELINE__RADE_RECEIVE_STEP_H