Skip to content

Commit

Permalink
Merge branch 'ms-audio-path' into ms-2020-experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
tmiw committed Jul 1, 2022
2 parents 8f73a54 + d803330 commit cacf8d0
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 93 deletions.
196 changes: 103 additions & 93 deletions src/freedv_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "pipeline/FreeDVTransmitStep.h"
#include "pipeline/FreeDVReceiveStep.h"

using namespace std::placeholders;

static const char* GetCurrentModeStrImpl_(int mode)
{
switch(mode)
Expand Down Expand Up @@ -595,113 +597,121 @@ IPipelineStep* FreeDVInterface::createReceivePipeline(
parallelSteps.push_back(recvStep);
}

auto preProcessFn = [&](ParallelStep* stepObj) {
int rxIndex = 0;
std::shared_ptr<ReceivePipelineState> state = std::static_pointer_cast<ReceivePipelineState>(stepObj->getState());
state->preProcessFn = std::bind(&FreeDVInterface::preProcessRxFn_, this, _1);
state->postProcessFn = std::bind(&FreeDVInterface::postProcessRxFn_, this, _1);

auto parallelStep = new ParallelStep(
inputSampleRate,
outputSampleRate,
!singleRxThread_,
state->preProcessFn,
state->postProcessFn,
parallelSteps,
state
);

return parallelStep;
}

// Set initial state for each step prior to execution.
for (auto& step : stepObj->getParallelSteps())
{
assert(step != nullptr);

FreeDVReceiveStep* castedStep = (FreeDVReceiveStep*)step.get();
castedStep->setSigPwrAvg(*state->getSigPwrAvgFn());
castedStep->setChannelNoiseEnable(state->getChannelNoiseFn(), state->getChannelNoiseSnrFn());
castedStep->setFreqOffset(state->getFreqOffsetFn());
}
int FreeDVInterface::preProcessRxFn_(ParallelStep* stepObj)
{
int rxIndex = 0;
std::shared_ptr<ReceivePipelineState> state = std::static_pointer_cast<ReceivePipelineState>(stepObj->getState());

// Set initial state for each step prior to execution.
for (auto& step : stepObj->getParallelSteps())
{
assert(step != nullptr);

// If the current RX mode is still sync'd, only process through that one.
for (auto& dv : dvObjects_)
FreeDVReceiveStep* castedStep = (FreeDVReceiveStep*)step.get();
castedStep->setSigPwrAvg(*state->getSigPwrAvgFn());
castedStep->setChannelNoiseEnable(state->getChannelNoiseFn(), state->getChannelNoiseSnrFn());
castedStep->setFreqOffset(state->getFreqOffsetFn());
}

// If the current RX mode is still sync'd, only process through that one.
for (auto& dv : dvObjects_)
{
if (dv == currentRxMode_ && freedv_get_sync(currentRxMode_))
{
if (dv == currentRxMode_ && freedv_get_sync(currentRxMode_))
{
return rxIndex;
}
rxIndex++;
return rxIndex;
}

return -1;
};
rxIndex++;
}

auto postProcessFn = [&](ParallelStep* stepObj) {
std::shared_ptr<ReceivePipelineState> state = std::static_pointer_cast<ReceivePipelineState>(stepObj->getState());
return -1;
};

// If the current RX mode is still sync'd, only let that one out.
int rxIndex = 0;
int indexWithSync = 0;
int maxSyncFound = -25;
struct freedv* dvWithSync = nullptr;
int FreeDVInterface::postProcessRxFn_(ParallelStep* stepObj)
{
std::shared_ptr<ReceivePipelineState> state = std::static_pointer_cast<ReceivePipelineState>(stepObj->getState());

for (auto& dv : dvObjects_)
// If the current RX mode is still sync'd, only let that one out.
int rxIndex = 0;
int indexWithSync = 0;
int maxSyncFound = -25;
struct freedv* dvWithSync = nullptr;

for (auto& dv : dvObjects_)
{
if (dv == currentRxMode_ && freedv_get_sync(currentRxMode_))
{
if (dv == currentRxMode_ && freedv_get_sync(currentRxMode_))
{
dvWithSync = dv;
indexWithSync = rxIndex;
goto skipSyncCheck;
}
rxIndex++;
dvWithSync = dv;
indexWithSync = rxIndex;
goto skipSyncCheck;
}

// Otherwise, find the mode that's sync'd and has the highest SNR.
rxIndex = 0;
for (auto& dv : dvObjects_)
{
struct MODEM_STATS *tmpStats = &modemStatsList_[rxIndex];
freedv_get_modem_extended_stats(dv, tmpStats);

if (!(isnan(tmpStats->snr_est) || isinf(tmpStats->snr_est))) {
snrVals_[rxIndex] = 0.95*snrVals_[rxIndex] + (1.0 - 0.95)*tmpStats->snr_est;
}
int snr = (int)(snrVals_[rxIndex]+0.5);

if (snr > maxSyncFound && tmpStats->sync != 0)
{
maxSyncFound = snr;
indexWithSync = rxIndex;
dvWithSync = dv;
}

rxIndex++;
rxIndex++;
}

// Otherwise, find the mode that's sync'd and has the highest SNR.
rxIndex = 0;
for (auto& dv : dvObjects_)
{
struct MODEM_STATS *tmpStats = &modemStatsList_[rxIndex];
freedv_get_modem_extended_stats(dv, tmpStats);

if (!(isnan(tmpStats->snr_est) || isinf(tmpStats->snr_est))) {
snrVals_[rxIndex] = 0.95*snrVals_[rxIndex] + (1.0 - 0.95)*tmpStats->snr_est;
}
int snr = (int)(snrVals_[rxIndex]+0.5);

bool canUnsquelch = !squelchEnabled_ ||
(squelchEnabled_ && snr >= squelchVals_[rxIndex]);

if (dvWithSync == nullptr)
if (snr > maxSyncFound && tmpStats->sync != 0 && canUnsquelch)
{
// Default to the first DV object if there's no sync.
indexWithSync = 0;
dvWithSync = dvObjects_[0];
maxSyncFound = snr;
indexWithSync = rxIndex;
dvWithSync = dv;
}

skipSyncCheck:
struct MODEM_STATS* stats = getCurrentRxModemStats();

// grab extended stats so we can plot spectrum, scatter diagram etc
freedv_get_modem_extended_stats(dvWithSync, stats);

// Update sync as it may have gone stale during decode
*state->getRxStateFn() = stats->sync != 0;

if (*state->getRxStateFn())
{
rxMode_ = enabledModes_[indexWithSync];
currentRxMode_ = dvWithSync;
lastSyncRxMode_ = currentRxMode_;
}
rxIndex++;
}

*state->getSigPwrAvgFn() = ((FreeDVReceiveStep*)stepObj->getParallelSteps()[indexWithSync].get())->getSigPwrAvg();

return indexWithSync;
};
if (dvWithSync == nullptr)
{
// Default to the first DV object if there's no sync.
indexWithSync = 0;
dvWithSync = dvObjects_[0];
}

skipSyncCheck:
struct MODEM_STATS* stats = getCurrentRxModemStats();

auto parallelStep = new ParallelStep(
inputSampleRate,
outputSampleRate,
!singleRxThread_,
preProcessFn,
postProcessFn,
parallelSteps,
state
);
// grab extended stats so we can plot spectrum, scatter diagram etc
freedv_get_modem_extended_stats(dvWithSync, stats);

// Update sync as it may have gone stale during decode
*state->getRxStateFn() = stats->sync != 0;

if (*state->getRxStateFn())
{
rxMode_ = enabledModes_[indexWithSync];
currentRxMode_ = dvWithSync;
lastSyncRxMode_ = currentRxMode_;
}

*state->getSigPwrAvgFn() = ((FreeDVReceiveStep*)stepObj->getParallelSteps()[indexWithSync].get())->getSigPwrAvg();

return parallelStep;
}
return indexWithSync;
};
6 changes: 6 additions & 0 deletions src/freedv_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <samplerate.h>

class IPipelineStep;
class ParallelStep;

class FreeDVInterface
{
Expand Down Expand Up @@ -122,6 +123,8 @@ class FreeDVInterface
std::function<int()> getChannelNoiseSnrFn;
std::function<float()> getFreqOffsetFn;
std::function<float*()> getSigPwrAvgFn;
std::function<int(ParallelStep*)> preProcessFn;
std::function<int(ParallelStep*)> postProcessFn;
};

struct FreeDVTextFnState
Expand Down Expand Up @@ -163,6 +166,9 @@ class FreeDVInterface

std::deque<reliable_text_t> reliableText_;
std::string receivedReliableText_;

int preProcessRxFn_(ParallelStep* ps);
int postProcessRxFn_(ParallelStep* ps);
};

#endif // CODEC2_INTERFACE_H

0 comments on commit cacf8d0

Please sign in to comment.