mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-10 18:43:28 -05:00
WDSP Rx: first basic implementation
This commit is contained in:
parent
d0391e3516
commit
b2303b028c
@ -251,7 +251,7 @@ void WDSPRx::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
|
||||
<< " m_filterIndex: " << settings.m_filterIndex
|
||||
<< " [m_spanLog2: " << settings.m_filterBank[settings.m_filterIndex].m_spanLog2
|
||||
<< " m_rfBandwidth: " << settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth
|
||||
<< " m_highCutoff: " << settings.m_filterBank[settings.m_filterIndex].m_highCutoff
|
||||
<< " m_lowCutoff: " << settings.m_filterBank[settings.m_filterIndex].m_lowCutoff
|
||||
<< " m_fftWindow: " << settings.m_filterBank[settings.m_filterIndex].m_fftWindow << "]"
|
||||
<< " m_volume: " << settings.m_volume
|
||||
@ -260,16 +260,10 @@ void WDSPRx::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
<< " m_dsb: " << settings.m_dsb
|
||||
<< " m_audioMute: " << settings.m_audioMute
|
||||
<< " m_agcActive: " << settings.m_agc
|
||||
<< " m_agcClamping: " << settings.m_agcClamping
|
||||
<< " m_agcTimeLog2: " << settings.m_agcTimeLog2
|
||||
<< " agcPowerThreshold: " << settings.m_agcPowerThreshold
|
||||
<< " agcThresholdGate: " << settings.m_agcThresholdGate
|
||||
<< " m_dnr: " << settings.m_dnr
|
||||
<< " m_dnrScheme: " << settings.m_dnrScheme
|
||||
<< " m_dnrAboveAvgFactor: " << settings.m_dnrAboveAvgFactor
|
||||
<< " m_dnrSigmaFactor: " << settings.m_dnrSigmaFactor
|
||||
<< " m_dnrNbPeaks: " << settings.m_dnrNbPeaks
|
||||
<< " m_dnrAlpha: " << settings.m_dnrAlpha
|
||||
<< " m_agcMode: " << settings.m_agcMode
|
||||
<< " m_agcGain: " << settings.m_agcGain
|
||||
<< " m_agcSlope: " << settings.m_agcSlope
|
||||
<< " m_agcHangThreshold: " << settings.m_agcHangThreshold
|
||||
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||
<< " m_streamIndex: " << settings.m_streamIndex
|
||||
<< " m_useReverseAPI: " << settings.m_useReverseAPI
|
||||
@ -290,7 +284,7 @@ void WDSPRx::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
if ((m_settings.m_filterBank[m_settings.m_filterIndex].m_spanLog2 != settings.m_filterBank[settings.m_filterIndex].m_spanLog2) || force) {
|
||||
reverseAPIKeys.append("spanLog2");
|
||||
}
|
||||
if ((m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth != settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth) || force) {
|
||||
if ((m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff != settings.m_filterBank[settings.m_filterIndex].m_highCutoff) || force) {
|
||||
reverseAPIKeys.append("rfBandwidth");
|
||||
}
|
||||
if ((m_settings.m_filterBank[m_settings.m_filterIndex].m_lowCutoff != settings.m_filterBank[settings.m_filterIndex].m_lowCutoff) || force) {
|
||||
@ -302,18 +296,6 @@ void WDSPRx::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
if ((m_settings.m_volume != settings.m_volume) || force) {
|
||||
reverseAPIKeys.append("volume");
|
||||
}
|
||||
if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) || force) {
|
||||
reverseAPIKeys.append("agcTimeLog2");
|
||||
}
|
||||
if ((m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) || force) {
|
||||
reverseAPIKeys.append("agcPowerThreshold");
|
||||
}
|
||||
if ((m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) || force) {
|
||||
reverseAPIKeys.append("agcThresholdGate");
|
||||
}
|
||||
if ((m_settings.m_agcClamping != settings.m_agcClamping) || force) {
|
||||
reverseAPIKeys.append("agcClamping");
|
||||
}
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force) {
|
||||
reverseAPIKeys.append("audioDeviceName");
|
||||
}
|
||||
@ -332,24 +314,6 @@ void WDSPRx::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
if ((m_settings.m_agc != settings.m_agc) || force) {
|
||||
reverseAPIKeys.append("agc");
|
||||
}
|
||||
if ((m_settings.m_dnr != settings.m_dnr) || force) {
|
||||
reverseAPIKeys.append("dnr");
|
||||
}
|
||||
if ((m_settings.m_dnrScheme != settings.m_dnrScheme) || force) {
|
||||
reverseAPIKeys.append("dnrScheme");
|
||||
}
|
||||
if ((m_settings.m_dnrAboveAvgFactor != settings.m_dnrAboveAvgFactor) || force) {
|
||||
reverseAPIKeys.append("dnrAboveAvgFactor");
|
||||
}
|
||||
if ((m_settings.m_dnrSigmaFactor != settings.m_dnrSigmaFactor) || force) {
|
||||
reverseAPIKeys.append("dnrSigmaFactor");
|
||||
}
|
||||
if ((m_settings.m_dnrNbPeaks != settings.m_dnrNbPeaks) || force) {
|
||||
reverseAPIKeys.append("dnrNbPeaks");
|
||||
}
|
||||
if ((m_settings.m_dnrAlpha != settings.m_dnrAlpha) || force) {
|
||||
reverseAPIKeys.append("dnrAlpha");
|
||||
}
|
||||
|
||||
if (m_settings.m_streamIndex != settings.m_streamIndex)
|
||||
{
|
||||
@ -367,12 +331,12 @@ void WDSPRx::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
}
|
||||
|
||||
if ((settings.m_dsb != m_settings.m_dsb)
|
||||
|| (settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth != m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth)
|
||||
|| (settings.m_filterBank[settings.m_filterIndex].m_highCutoff != m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff)
|
||||
|| (settings.m_filterBank[settings.m_filterIndex].m_lowCutoff != m_settings.m_filterBank[m_settings.m_filterIndex].m_lowCutoff) || force)
|
||||
{
|
||||
SpectrumSettings spectrumSettings = m_spectrumVis.getSettings();
|
||||
spectrumSettings.m_ssb = !settings.m_dsb;
|
||||
spectrumSettings.m_usb = (settings.m_filterBank[settings.m_filterIndex].m_lowCutoff < settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth);
|
||||
spectrumSettings.m_usb = (settings.m_filterBank[settings.m_filterIndex].m_lowCutoff < settings.m_filterBank[settings.m_filterIndex].m_highCutoff);
|
||||
SpectrumVis::MsgConfigureSpectrumVis *msg = SpectrumVis::MsgConfigureSpectrumVis::create(spectrumSettings, false);
|
||||
m_spectrumVis.getInputMessageQueue()->push(msg);
|
||||
}
|
||||
@ -508,7 +472,7 @@ void WDSPRx::webapiUpdateChannelSettings(
|
||||
settings.m_filterBank[settings.m_filterIndex].m_spanLog2 = response.getSsbDemodSettings()->getSpanLog2();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rfBandwidth")) {
|
||||
settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth = response.getSsbDemodSettings()->getRfBandwidth();
|
||||
settings.m_filterBank[settings.m_filterIndex].m_highCutoff = response.getSsbDemodSettings()->getRfBandwidth();
|
||||
}
|
||||
if (channelSettingsKeys.contains("lowCutoff")) {
|
||||
settings.m_filterBank[settings.m_filterIndex].m_lowCutoff = response.getSsbDemodSettings()->getLowCutoff();
|
||||
@ -534,33 +498,6 @@ void WDSPRx::webapiUpdateChannelSettings(
|
||||
if (channelSettingsKeys.contains("agc")) {
|
||||
settings.m_agc = response.getSsbDemodSettings()->getAgc() != 0;
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcClamping")) {
|
||||
settings.m_agcClamping = response.getSsbDemodSettings()->getAgcClamping() != 0;
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcTimeLog2")) {
|
||||
settings.m_agcTimeLog2 = response.getSsbDemodSettings()->getAgcTimeLog2();
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcPowerThreshold")) {
|
||||
settings.m_agcPowerThreshold = response.getSsbDemodSettings()->getAgcPowerThreshold();
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcThresholdGate")) {
|
||||
settings.m_agcThresholdGate = response.getSsbDemodSettings()->getAgcThresholdGate();
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnr")) {
|
||||
settings.m_dnr = response.getSsbDemodSettings()->getDnr() != 0;
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrAboveAvgFactor")) {
|
||||
settings.m_dnrAboveAvgFactor = response.getSsbDemodSettings()->getDnrAboveAvgFactor();
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrSigmaFactor")) {
|
||||
settings.m_dnrSigmaFactor = response.getSsbDemodSettings()->getDnrSigmaFactor();
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrNbPeaks")) {
|
||||
settings.m_dnrNbPeaks = response.getSsbDemodSettings()->getDnrNbPeaks();
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrAlpha")) {
|
||||
settings.m_dnrAlpha = response.getSsbDemodSettings()->getDnrAlpha();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor")) {
|
||||
settings.m_rgbColor = response.getSsbDemodSettings()->getRgbColor();
|
||||
}
|
||||
@ -616,7 +553,7 @@ void WDSPRx::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
|
||||
response.getSsbDemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
|
||||
response.getSsbDemodSettings()->setFilterIndex(settings.m_filterIndex);
|
||||
response.getSsbDemodSettings()->setSpanLog2(settings.m_filterBank[settings.m_filterIndex].m_spanLog2);
|
||||
response.getSsbDemodSettings()->setRfBandwidth(settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth);
|
||||
response.getSsbDemodSettings()->setRfBandwidth(settings.m_filterBank[settings.m_filterIndex].m_highCutoff);
|
||||
response.getSsbDemodSettings()->setLowCutoff(settings.m_filterBank[settings.m_filterIndex].m_lowCutoff);
|
||||
response.getSsbDemodSettings()->setFftWindow((int) settings.m_filterBank[settings.m_filterIndex].m_fftWindow);
|
||||
response.getSsbDemodSettings()->setVolume(settings.m_volume);
|
||||
@ -625,16 +562,6 @@ void WDSPRx::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
|
||||
response.getSsbDemodSettings()->setDsb(settings.m_dsb ? 1 : 0);
|
||||
response.getSsbDemodSettings()->setAudioMute(settings.m_audioMute ? 1 : 0);
|
||||
response.getSsbDemodSettings()->setAgc(settings.m_agc ? 1 : 0);
|
||||
response.getSsbDemodSettings()->setAgcClamping(settings.m_agcClamping ? 1 : 0);
|
||||
response.getSsbDemodSettings()->setAgcTimeLog2(settings.m_agcTimeLog2);
|
||||
response.getSsbDemodSettings()->setAgcPowerThreshold(settings.m_agcPowerThreshold);
|
||||
response.getSsbDemodSettings()->setAgcThresholdGate(settings.m_agcThresholdGate);
|
||||
response.getSsbDemodSettings()->setDnr(settings.m_dnr ? 1 : 0);
|
||||
response.getSsbDemodSettings()->setDnrScheme(settings.m_dnrScheme);
|
||||
response.getSsbDemodSettings()->setDnrAboveAvgFactor(settings.m_dnrAboveAvgFactor);
|
||||
response.getSsbDemodSettings()->setDnrSigmaFactor(settings.m_dnrSigmaFactor);
|
||||
response.getSsbDemodSettings()->setDnrNbPeaks(settings.m_dnrNbPeaks);
|
||||
response.getSsbDemodSettings()->setDnrAlpha(settings.m_dnrAlpha);
|
||||
response.getSsbDemodSettings()->setRgbColor(settings.m_rgbColor);
|
||||
|
||||
if (response.getSsbDemodSettings()->getTitle()) {
|
||||
@ -799,7 +726,7 @@ void WDSPRx::webapiFormatChannelSettings(
|
||||
swgSSBDemodSettings->setSpanLog2(settings.m_filterBank[settings.m_filterIndex].m_spanLog2);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rfBandwidth") || force) {
|
||||
swgSSBDemodSettings->setRfBandwidth(settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth);
|
||||
swgSSBDemodSettings->setRfBandwidth(settings.m_filterBank[settings.m_filterIndex].m_highCutoff);
|
||||
}
|
||||
if (channelSettingsKeys.contains("lowCutoff") || force) {
|
||||
swgSSBDemodSettings->setLowCutoff(settings.m_filterBank[settings.m_filterIndex].m_lowCutoff);
|
||||
@ -825,33 +752,6 @@ void WDSPRx::webapiFormatChannelSettings(
|
||||
if (channelSettingsKeys.contains("agc") || force) {
|
||||
swgSSBDemodSettings->setAgc(settings.m_agc ? 1 : 0);
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcClamping") || force) {
|
||||
swgSSBDemodSettings->setAgcClamping(settings.m_agcClamping ? 1 : 0);
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcTimeLog2") || force) {
|
||||
swgSSBDemodSettings->setAgcTimeLog2(settings.m_agcTimeLog2);
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcPowerThreshold") || force) {
|
||||
swgSSBDemodSettings->setAgcPowerThreshold(settings.m_agcPowerThreshold);
|
||||
}
|
||||
if (channelSettingsKeys.contains("agcThresholdGate") || force) {
|
||||
swgSSBDemodSettings->setAgcThresholdGate(settings.m_agcThresholdGate);
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnr")) {
|
||||
swgSSBDemodSettings->setDnr(settings.m_dnr ? 1 : 0);
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrAboveAvgFactor")) {
|
||||
swgSSBDemodSettings->setDnrAboveAvgFactor(settings.m_dnrAboveAvgFactor);
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrSigmaFactor")) {
|
||||
swgSSBDemodSettings->setDnrSigmaFactor(settings.m_dnrSigmaFactor);
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrNbPeaks")) {
|
||||
swgSSBDemodSettings->setDnrNbPeaks(settings.m_dnrNbPeaks);
|
||||
}
|
||||
if (channelSettingsKeys.contains("dnrAlpha")) {
|
||||
swgSSBDemodSettings->setDnrAlpha(settings.m_dnrAlpha);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor") || force) {
|
||||
swgSSBDemodSettings->setRgbColor(settings.m_rgbColor);
|
||||
}
|
||||
|
@ -202,43 +202,18 @@ void WDSPRxGUI::on_agc_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_agc = checked;
|
||||
applySettings();
|
||||
displayAGC();
|
||||
}
|
||||
|
||||
void WDSPRxGUI::on_agcClamping_toggled(bool checked)
|
||||
void WDSPRxGUI::on_dnr_toggled(bool)
|
||||
{
|
||||
m_settings.m_agcClamping = checked;
|
||||
applySettings();
|
||||
// TBD
|
||||
}
|
||||
|
||||
void WDSPRxGUI::on_dnr_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_dnr = checked;
|
||||
m_settings.m_filterBank[m_settings.m_filterIndex].m_dnr = m_settings.m_dnr;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void WDSPRxGUI::on_agcTimeLog2_valueChanged(int value)
|
||||
void WDSPRxGUI::on_agcGain_valueChanged(int value)
|
||||
{
|
||||
QString s = QString::number((1<<value), 'f', 0);
|
||||
ui->agcTimeText->setText(s);
|
||||
m_settings.m_agcTimeLog2 = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void WDSPRxGUI::on_agcPowerThreshold_valueChanged(int value)
|
||||
{
|
||||
displayAGCPowerThreshold(value);
|
||||
m_settings.m_agcPowerThreshold = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void WDSPRxGUI::on_agcThresholdGate_valueChanged(int value)
|
||||
{
|
||||
int agcThresholdGate = value < 20 ? value : ((value - 20) * 10) + 20;
|
||||
QString s = QString::number(agcThresholdGate, 'f', 0);
|
||||
ui->agcThresholdGateText->setText(s);
|
||||
m_settings.m_agcThresholdGate = agcThresholdGate;
|
||||
ui->agcGainText->setText(s);
|
||||
m_settings.m_agcGain = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -271,7 +246,7 @@ void WDSPRxGUI::on_flipSidebands_clicked(bool checked)
|
||||
|
||||
void WDSPRxGUI::on_fftWindow_currentIndexChanged(int index)
|
||||
{
|
||||
m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow = (FFTWindow::Function) index;
|
||||
m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow = index;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -594,7 +569,7 @@ void WDSPRxGUI::applyBandwidths(unsigned int spanLog2, bool force)
|
||||
|
||||
m_settings.m_dsb = dsb;
|
||||
m_settings.m_filterBank[m_settings.m_filterIndex].m_spanLog2 = spanLog2;
|
||||
m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth = bw * 100;
|
||||
m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff = bw * 100;
|
||||
m_settings.m_filterBank[m_settings.m_filterIndex].m_lowCutoff = lw * 100;
|
||||
|
||||
applySettings(force);
|
||||
@ -611,7 +586,7 @@ void WDSPRxGUI::displaySettings()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setBandwidth(m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth * 2);
|
||||
m_channelMarker.setBandwidth(m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff * 2);
|
||||
m_channelMarker.setTitle(m_settings.m_title);
|
||||
m_channelMarker.setLowCutoff(m_settings.m_filterBank[m_settings.m_filterIndex].m_lowCutoff);
|
||||
|
||||
@ -629,7 +604,7 @@ void WDSPRxGUI::displaySettings()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth < 0)
|
||||
if (m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff < 0)
|
||||
{
|
||||
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
||||
ui->dsb->setIcon(m_iconDSBLSB);
|
||||
@ -653,14 +628,15 @@ void WDSPRxGUI::displaySettings()
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
ui->agc->setChecked(m_settings.m_agc);
|
||||
displayAGC();
|
||||
ui->agcClamping->setChecked(m_settings.m_agcClamping);
|
||||
ui->agcGain->setValue(m_settings.m_agcGain);
|
||||
QString s = QString::number((ui->agcGain->value()), 'f', 0);
|
||||
ui->agcGainText->setText(s);
|
||||
ui->dnr->setChecked(m_settings.m_dnr);
|
||||
ui->audioBinaural->setChecked(m_settings.m_audioBinaural);
|
||||
ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels);
|
||||
ui->audioMute->setChecked(m_settings.m_audioMute);
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
ui->fftWindow->setCurrentIndex((int) m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow);
|
||||
ui->fftWindow->setCurrentIndex(m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow);
|
||||
|
||||
// Prevent uncontrolled triggering of applyBandwidths
|
||||
ui->spanLog2->blockSignals(true);
|
||||
@ -674,8 +650,8 @@ void WDSPRxGUI::displaySettings()
|
||||
ui->dsb->setChecked(m_settings.m_dsb);
|
||||
ui->spanLog2->setValue(1 + ui->spanLog2->maximum() - m_settings.m_filterBank[m_settings.m_filterIndex].m_spanLog2);
|
||||
|
||||
ui->BW->setValue(m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth / 100.0);
|
||||
QString s = QString::number(m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth/1000.0, 'f', 1);
|
||||
ui->BW->setValue(m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff / 100.0);
|
||||
s = QString::number(m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff/1000.0, 'f', 1);
|
||||
|
||||
if (m_settings.m_dsb) {
|
||||
ui->BWText->setText(tr("%1%2k").arg(QChar(0xB1, 0x00)).arg(s));
|
||||
@ -697,14 +673,6 @@ void WDSPRxGUI::displaySettings()
|
||||
ui->volume->setValue(volume);
|
||||
ui->volumeText->setText(QString("%1").arg(volume));
|
||||
|
||||
ui->agcTimeLog2->setValue(m_settings.m_agcTimeLog2);
|
||||
s = QString::number((1<<ui->agcTimeLog2->value()), 'f', 0);
|
||||
ui->agcTimeText->setText(s);
|
||||
|
||||
ui->agcPowerThreshold->setValue(m_settings.m_agcPowerThreshold);
|
||||
displayAGCPowerThreshold(ui->agcPowerThreshold->value());
|
||||
displayAGCThresholdGate(m_settings.m_agcThresholdGate);
|
||||
|
||||
updateIndexLabel();
|
||||
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
@ -712,42 +680,9 @@ void WDSPRxGUI::displaySettings()
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void WDSPRxGUI::displayAGC()
|
||||
void WDSPRxGUI::agcSetupDialog()
|
||||
{
|
||||
// Disable controls only valid when AGC is enabled
|
||||
ui->agcClamping->setEnabled(m_settings.m_agc);
|
||||
ui->agcTimeLog2->setEnabled(m_settings.m_agc);
|
||||
ui->agcTimeText->setEnabled(m_settings.m_agc);
|
||||
ui->agcPowerThreshold->setEnabled(m_settings.m_agc);
|
||||
ui->agcPowerThresholdText->setEnabled(m_settings.m_agc);
|
||||
ui->agcThresholdGate->setEnabled(m_settings.m_agc);
|
||||
ui->agcThresholdGateText->setEnabled(m_settings.m_agc);
|
||||
}
|
||||
|
||||
void WDSPRxGUI::displayAGCPowerThreshold(int value)
|
||||
{
|
||||
if (value == WDSPRxSettings::m_minPowerThresholdDB)
|
||||
{
|
||||
ui->agcPowerThresholdText->setText("---");
|
||||
}
|
||||
else
|
||||
{
|
||||
QString s = QString::number(value, 'f', 0);
|
||||
ui->agcPowerThresholdText->setText(s);
|
||||
}
|
||||
}
|
||||
|
||||
void WDSPRxGUI::displayAGCThresholdGate(int value)
|
||||
{
|
||||
QString s = QString::number(value, 'f', 0);
|
||||
ui->agcThresholdGateText->setText(s);
|
||||
int dialValue = value;
|
||||
|
||||
if (value > 20) {
|
||||
dialValue = ((value - 20) / 10) + 20;
|
||||
}
|
||||
|
||||
ui->agcThresholdGate->setValue(dialValue);
|
||||
// TODO
|
||||
}
|
||||
|
||||
void WDSPRxGUI::leaveEvent(QEvent* event)
|
||||
@ -879,11 +814,8 @@ void WDSPRxGUI::makeUIConnections()
|
||||
QObject::connect(ui->lowCut, &TickedSlider::valueChanged, this, &WDSPRxGUI::on_lowCut_valueChanged);
|
||||
QObject::connect(ui->volume, &QDial::valueChanged, this, &WDSPRxGUI::on_volume_valueChanged);
|
||||
QObject::connect(ui->agc, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_agc_toggled);
|
||||
QObject::connect(ui->agcClamping, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_agcClamping_toggled);
|
||||
QObject::connect(ui->dnr, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_dnr_toggled);
|
||||
QObject::connect(ui->agcTimeLog2, &QDial::valueChanged, this, &WDSPRxGUI::on_agcTimeLog2_valueChanged);
|
||||
QObject::connect(ui->agcPowerThreshold, &QDial::valueChanged, this, &WDSPRxGUI::on_agcPowerThreshold_valueChanged);
|
||||
QObject::connect(ui->agcThresholdGate, &QDial::valueChanged, this, &WDSPRxGUI::on_agcThresholdGate_valueChanged);
|
||||
QObject::connect(ui->agcGain, &QDial::valueChanged, this, &WDSPRxGUI::on_agcGain_valueChanged);
|
||||
QObject::connect(ui->audioMute, &QToolButton::toggled, this, &WDSPRxGUI::on_audioMute_toggled);
|
||||
QObject::connect(ui->spanLog2, &QSlider::valueChanged, this, &WDSPRxGUI::on_spanLog2_valueChanged);
|
||||
QObject::connect(ui->flipSidebands, &QPushButton::clicked, this, &WDSPRxGUI::on_flipSidebands_clicked);
|
||||
|
@ -102,9 +102,6 @@ private:
|
||||
void applyBandwidths(unsigned int spanLog2, bool force = false);
|
||||
unsigned int spanLog2Max();
|
||||
void displaySettings();
|
||||
void displayAGC();
|
||||
void displayAGCPowerThreshold(int value);
|
||||
void displayAGCThresholdGate(int value);
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void updateAbsoluteCenterFrequency();
|
||||
@ -122,11 +119,8 @@ private slots:
|
||||
void on_lowCut_valueChanged(int value);
|
||||
void on_volume_valueChanged(int value);
|
||||
void on_agc_toggled(bool checked);
|
||||
void on_agcClamping_toggled(bool checked);
|
||||
void on_dnr_toggled(bool checked);
|
||||
void on_agcTimeLog2_valueChanged(int value);
|
||||
void on_agcPowerThreshold_valueChanged(int value);
|
||||
void on_agcThresholdGate_valueChanged(int value);
|
||||
void on_agcGain_valueChanged(int value);
|
||||
void on_audioMute_toggled(bool checked);
|
||||
void on_spanLog2_valueChanged(int value);
|
||||
void on_flipSidebands_clicked(bool checked);
|
||||
@ -138,6 +132,7 @@ private slots:
|
||||
void audioSelect(const QPoint& p);
|
||||
void dnrSetupDialog(const QPoint& p);
|
||||
void dnrSetup(int valueChanged);
|
||||
void agcSetupDialog();
|
||||
void tick();
|
||||
};
|
||||
|
||||
|
@ -377,42 +377,7 @@
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bart</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>B-H</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FT</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Ham</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Han</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Rec</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Kai</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Black</string>
|
||||
<string>B-H4</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
@ -856,40 +821,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="agcClamping">
|
||||
<property name="toolTip">
|
||||
<string>Toggle AGC clamping to maximum allowable signal</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CL</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="dnr">
|
||||
<property name="toolTip">
|
||||
<string>Toggle Digital Noise Reduction</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NR</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="agcTimeLog2">
|
||||
<widget class="QDial" name="agcGain">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
@ -900,120 +832,21 @@
|
||||
<string>AGC time constant (ms in log2 steps)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>4</number>
|
||||
<number>-20</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>11</number>
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>7</number>
|
||||
<number>80</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="agcTimeText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>AGC time constant (ms)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0000</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="agcPowerThreshold">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Power threshold (dB)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-120</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-40</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="agcPowerThresholdText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>26</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Power threshold (dB)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-000</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="agcThresholdGate">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Power threshold gate (ms)</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>68</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="agcThresholdGateText">
|
||||
<widget class="QLabel" name="agcGainText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
@ -1031,6 +864,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="dnr">
|
||||
<property name="toolTip">
|
||||
<string>Toggle Digital Noise Reduction</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NR</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -45,19 +45,13 @@ void WDSPRxSettings::resetToDefaults()
|
||||
m_audioFlipChannels = false;
|
||||
m_dsb = false;
|
||||
m_audioMute = false;
|
||||
m_agc = false;
|
||||
m_agcClamping = false;
|
||||
m_agcPowerThreshold = -100;
|
||||
m_agcThresholdGate = 4;
|
||||
m_agcTimeLog2 = 7;
|
||||
m_agc = true;
|
||||
m_agcMode = AGCMedium;
|
||||
m_agcGain = 80;
|
||||
m_agcSlope = 35; // 3.5 dB
|
||||
m_agcHangThreshold = 0;
|
||||
m_volume = 1.0;
|
||||
m_inputFrequencyOffset = 0;
|
||||
m_dnr = false;
|
||||
m_dnrScheme = 0;
|
||||
m_dnrAboveAvgFactor = 40.0f;
|
||||
m_dnrSigmaFactor = 4.0f;
|
||||
m_dnrNbPeaks = 20;
|
||||
m_dnrAlpha = 1.0;
|
||||
m_rgbColor = QColor(0, 255, 0).rgb();
|
||||
m_title = "WDSP Receiver";
|
||||
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||
@ -87,10 +81,10 @@ QByteArray WDSPRxSettings::serialize() const
|
||||
s.writeBool(9, m_audioFlipChannels);
|
||||
s.writeBool(10, m_dsb);
|
||||
s.writeBool(11, m_agc);
|
||||
s.writeS32(12, m_agcTimeLog2);
|
||||
s.writeS32(13, m_agcPowerThreshold);
|
||||
s.writeS32(14, m_agcThresholdGate);
|
||||
s.writeBool(15, m_agcClamping);
|
||||
s.writeS32(12, (int) m_agcMode);
|
||||
s.writeS32(13, m_agcGain);
|
||||
s.writeS32(14, m_agcSlope);
|
||||
s.writeS32(15, m_agcHangThreshold);
|
||||
s.writeString(16, m_title);
|
||||
s.writeString(17, m_audioDeviceName);
|
||||
s.writeBool(18, m_useReverseAPI);
|
||||
@ -108,17 +102,11 @@ QByteArray WDSPRxSettings::serialize() const
|
||||
s.writeBlob(26, m_geometryBytes);
|
||||
s.writeBool(27, m_hidden);
|
||||
s.writeU32(29, m_filterIndex);
|
||||
s.writeBool(30, m_dnr);
|
||||
s.writeS32(31, m_dnrScheme);
|
||||
s.writeFloat(32, m_dnrAboveAvgFactor);
|
||||
s.writeFloat(33, m_dnrSigmaFactor);
|
||||
s.writeS32(34, m_dnrNbPeaks);
|
||||
s.writeFloat(35, m_dnrAlpha);
|
||||
|
||||
for (unsigned int i = 0; i < 10; i++)
|
||||
{
|
||||
s.writeS32(100 + 10*i, m_filterBank[i].m_spanLog2);
|
||||
s.writeS32(101 + 10*i, m_filterBank[i].m_rfBandwidth / 100.0);
|
||||
s.writeS32(101 + 10*i, m_filterBank[i].m_highCutoff / 100.0);
|
||||
s.writeS32(102 + 10*i, m_filterBank[i].m_lowCutoff / 100.0);
|
||||
s.writeS32(103 + 10*i, (int) m_filterBank[i].m_fftWindow);
|
||||
s.writeBool(104 + 10*i, m_filterBank[i].m_dnr);
|
||||
@ -163,12 +151,13 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
|
||||
d.readBool(8, &m_audioBinaural, false);
|
||||
d.readBool(9, &m_audioFlipChannels, false);
|
||||
d.readBool(10, &m_dsb, false);
|
||||
d.readBool(11, &m_agc, false);
|
||||
d.readS32(12, &m_agcTimeLog2, 7);
|
||||
d.readS32(13, &m_agcPowerThreshold, -40);
|
||||
d.readS32(14, &m_agcThresholdGate, 4);
|
||||
d.readBool(15, &m_agcClamping, false);
|
||||
d.readString(16, &m_title, "SSB Demodulator");
|
||||
d.readBool(11, &m_agc, true);
|
||||
d.readS32(12, &tmp, 2);
|
||||
m_agcMode = (AGCMode) tmp;
|
||||
d.readS32(13, &m_agcGain, 80);
|
||||
d.readS32(14, &m_agcSlope, 35);
|
||||
d.readS32(15, &m_agcHangThreshold, 0);
|
||||
d.readString(16, &m_title, "WDSP Receiver");
|
||||
d.readString(17, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
|
||||
d.readBool(18, &m_useReverseAPI, false);
|
||||
d.readString(19, &m_reverseAPIAddress, "127.0.0.1");
|
||||
@ -197,18 +186,12 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
|
||||
d.readBool(27, &m_hidden, false);
|
||||
d.readU32(29, &utmp, 0);
|
||||
m_filterIndex = utmp < 10 ? utmp : 0;
|
||||
d.readBool(30, &m_dnr, false);
|
||||
d.readS32(31, &m_dnrScheme, 0);
|
||||
d.readFloat(32, &m_dnrAboveAvgFactor, 40.0f);
|
||||
d.readFloat(33, &m_dnrSigmaFactor, 4.0f);
|
||||
d.readS32(34, &m_dnrNbPeaks, 20);
|
||||
d.readFloat(35, &m_dnrAlpha, 1.0);
|
||||
|
||||
for (unsigned int i = 0; (i < 10); i++)
|
||||
{
|
||||
d.readS32(100 + 10*i, &m_filterBank[i].m_spanLog2, 3);
|
||||
d.readS32(101 + 10*i, &tmp, 30);
|
||||
m_filterBank[i].m_rfBandwidth = tmp * 100.0;
|
||||
m_filterBank[i].m_highCutoff = tmp * 100.0;
|
||||
d.readS32(102+ 10*i, &tmp, 3);
|
||||
m_filterBank[i].m_lowCutoff = tmp * 100.0;
|
||||
d.readS32(103 + 10*i, &tmp, (int) FFTWindow::Blackman);
|
||||
|
@ -28,9 +28,9 @@ class Serializable;
|
||||
struct WDSPRxFilterSettings
|
||||
{
|
||||
int m_spanLog2;
|
||||
Real m_rfBandwidth;
|
||||
Real m_highCutoff;
|
||||
Real m_lowCutoff;
|
||||
FFTWindow::Function m_fftWindow;
|
||||
int m_fftWindow; // 0: 4-term Blackman-Harris, 1: 7-term Blackman-Harris
|
||||
bool m_dnr;
|
||||
int m_dnrScheme;
|
||||
float m_dnrAboveAvgFactor;
|
||||
@ -40,16 +40,24 @@ struct WDSPRxFilterSettings
|
||||
|
||||
WDSPRxFilterSettings() :
|
||||
m_spanLog2(3),
|
||||
m_rfBandwidth(3000),
|
||||
m_highCutoff(3000),
|
||||
m_lowCutoff(300),
|
||||
m_fftWindow(FFTWindow::Blackman)
|
||||
m_fftWindow(0)
|
||||
{}
|
||||
};
|
||||
|
||||
struct WDSPRxSettings
|
||||
{
|
||||
enum AGCMode
|
||||
{
|
||||
AGCLong,
|
||||
AGCSlow,
|
||||
AGCMedium,
|
||||
AGCFast,
|
||||
};
|
||||
|
||||
qint32 m_inputFrequencyOffset;
|
||||
// Real m_rfBandwidth;
|
||||
// Real m_highCutoff;
|
||||
// Real m_lowCutoff;
|
||||
Real m_volume;
|
||||
// int m_spanLog2;
|
||||
@ -58,10 +66,10 @@ struct WDSPRxSettings
|
||||
bool m_dsb;
|
||||
bool m_audioMute;
|
||||
bool m_agc;
|
||||
bool m_agcClamping;
|
||||
int m_agcTimeLog2;
|
||||
int m_agcPowerThreshold;
|
||||
int m_agcThresholdGate;
|
||||
AGCMode m_agcMode;
|
||||
int m_agcGain; //!< Fixed gain if AGC is off else top gain
|
||||
int m_agcSlope;
|
||||
int m_agcHangThreshold;
|
||||
bool m_dnr;
|
||||
int m_dnrScheme;
|
||||
float m_dnrAboveAvgFactor;
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "util/messagequeue.h"
|
||||
#include "maincore.h"
|
||||
#include "RXA.hpp"
|
||||
#include "nbp.hpp"
|
||||
#include "meter.hpp"
|
||||
#include "patchpanel.hpp"
|
||||
#include "wcpAGC.hpp"
|
||||
|
||||
#include "wdsprxsink.h"
|
||||
|
||||
@ -34,9 +38,19 @@ const int WDSPRxSink::m_agcTarget = 3276; // 32768/10 -10 dB amplitude => -20 dB
|
||||
const int WDSPRxSink::m_wdspSampleRate = 48000;
|
||||
const int WDSPRxSink::m_wdspBufSize = 512;
|
||||
|
||||
WDSPRxSink::SpectrumProbe::SpectrumProbe(SampleVector& sampleVector) :
|
||||
m_sampleVector(sampleVector)
|
||||
{}
|
||||
|
||||
void WDSPRxSink::SpectrumProbe::proceed(const double *in, int nb_samples)
|
||||
{
|
||||
for (int i = 0; i < nb_samples; i++) {
|
||||
m_sampleVector.push_back(Sample{static_cast<FixReal>(in[2*i]*SDR_RX_SCALED), static_cast<FixReal>(in[2*i+1]*SDR_RX_SCALED)});
|
||||
}
|
||||
}
|
||||
|
||||
WDSPRxSink::WDSPRxSink() :
|
||||
m_audioBinaual(false),
|
||||
m_audioFlipChannels(false),
|
||||
m_dsb(false),
|
||||
m_audioMute(false),
|
||||
m_agc(12000, m_agcTarget, 1e-2),
|
||||
@ -48,13 +62,13 @@ WDSPRxSink::WDSPRxSink() :
|
||||
m_squelchDelayLine(2*48000),
|
||||
m_audioActive(false),
|
||||
m_spectrumSink(nullptr),
|
||||
m_spectrumProbe(m_sampleBuffer),
|
||||
m_inCount(0),
|
||||
m_audioFifo(24000),
|
||||
m_audioSampleRate(48000)
|
||||
{
|
||||
m_Bandwidth = 5000;
|
||||
m_LowCutoff = 300;
|
||||
m_volume = 2.0;
|
||||
m_spanLog2 = 3;
|
||||
m_channelSampleRate = 48000;
|
||||
m_channelFrequencyOffset = 0;
|
||||
|
||||
@ -67,10 +81,9 @@ WDSPRxSink::WDSPRxSink() :
|
||||
m_demodBufferFill = 0;
|
||||
|
||||
m_usb = true;
|
||||
m_magsq = 0.0;
|
||||
m_magsqSum = 0.0;
|
||||
m_magsqPeak = 0.0;
|
||||
m_magsqCount = 0;
|
||||
m_sAvg = 0.0;
|
||||
m_sPeak = 0.0;
|
||||
m_sCount = 1;
|
||||
|
||||
m_rxa = WDSP::RXA::create_rxa(
|
||||
m_wdspSampleRate, // input samplerate
|
||||
@ -78,11 +91,8 @@ WDSPRxSink::WDSPRxSink() :
|
||||
m_wdspSampleRate, // sample rate for mainstream dsp processing (dsp)
|
||||
m_wdspBufSize // number complex samples processed per buffer in mainstream dsp processing
|
||||
);
|
||||
SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, m_ssbFftLen);
|
||||
DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * m_ssbFftLen);
|
||||
|
||||
m_lowpassI.create(101, m_audioSampleRate, m_Bandwidth * 1.2);
|
||||
m_lowpassQ.create(101, m_audioSampleRate, m_Bandwidth * 1.2);
|
||||
m_rxa->setSpectrumProbe(&m_spectrumProbe);
|
||||
WDSP::RXA::SetPassband(*m_rxa, 0, m_Bandwidth);
|
||||
|
||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||
applySettings(m_settings, true);
|
||||
@ -91,8 +101,6 @@ WDSPRxSink::WDSPRxSink() :
|
||||
WDSPRxSink::~WDSPRxSink()
|
||||
{
|
||||
WDSP::RXA::destroy_rxa(m_rxa);
|
||||
delete SSBFilter;
|
||||
delete DSBFilter;
|
||||
}
|
||||
|
||||
void WDSPRxSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||
@ -127,159 +135,105 @@ void WDSPRxSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||
}
|
||||
}
|
||||
|
||||
void WDSPRxSink::getMagSqLevels(double& avg, double& peak, int& nbSamples)
|
||||
{
|
||||
avg = m_sAvg;
|
||||
peak = m_sPeak;
|
||||
nbSamples = m_sCount;
|
||||
}
|
||||
|
||||
void WDSPRxSink::processOneSample(Complex &ci)
|
||||
{
|
||||
fftfilt::cmplx *sideband;
|
||||
int n_out = 0;
|
||||
int decim = 1<<(m_spanLog2 - 1);
|
||||
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
||||
m_rxa->get_inbuff()[2*m_inCount] = ci.real() / SDR_RX_SCALED;
|
||||
m_rxa->get_inbuff()[2*m_inCount+1] = ci.imag() / SDR_RX_SCALED;
|
||||
|
||||
if (m_dsb) {
|
||||
n_out = DSBFilter->runDSB(ci, &sideband);
|
||||
} else {
|
||||
n_out = SSBFilter->runSSB(ci, &sideband, m_usb);
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_out; i++)
|
||||
if (++m_inCount == m_rxa->get_insize())
|
||||
{
|
||||
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
||||
// smart decimation with bit gain using float arithmetic (23 bits significand)
|
||||
WDSP::RXA::xrxa(m_rxa);
|
||||
|
||||
m_sum += sideband[i];
|
||||
|
||||
if (!(m_undersampleCount++ & decim_mask))
|
||||
for (int i = 0; i < m_rxa->get_outsize(); i++)
|
||||
{
|
||||
Real avgr = m_sum.real() / decim;
|
||||
Real avgi = m_sum.imag() / decim;
|
||||
m_magsq = (avgr * avgr + avgi * avgi) / (SDR_RX_SCALED*SDR_RX_SCALED);
|
||||
|
||||
m_magsqSum += m_magsq;
|
||||
|
||||
if (m_magsq > m_magsqPeak)
|
||||
if (i == 0)
|
||||
{
|
||||
m_magsqPeak = m_magsq;
|
||||
m_sCount = m_wdspBufSize;
|
||||
m_sAvg = WDSP::METER::GetMeter(*m_rxa, WDSP::RXA::RXA_S_AV);
|
||||
m_sPeak = WDSP::METER::GetMeter(*m_rxa, WDSP::RXA::RXA_S_PK);
|
||||
}
|
||||
|
||||
m_magsqCount++;
|
||||
|
||||
if (!m_dsb & !m_usb)
|
||||
{ // invert spectrum for LSB
|
||||
m_sampleBuffer.push_back(Sample(avgi, avgr));
|
||||
if (m_audioMute)
|
||||
{
|
||||
m_audioBuffer[m_audioBufferFill].r = 0;
|
||||
m_audioBuffer[m_audioBufferFill].l = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sampleBuffer.push_back(Sample(avgr, avgi));
|
||||
}
|
||||
const double& cr = m_rxa->get_outbuff()[2*i];
|
||||
const double& ci = m_rxa->get_outbuff()[2*i+1];
|
||||
qint16 zr = cr * 32768.0;
|
||||
qint16 zi = ci * 32768.0;
|
||||
m_audioBuffer[m_audioBufferFill].r = zr * m_volume;
|
||||
m_audioBuffer[m_audioBufferFill].l = zi * m_volume;
|
||||
|
||||
m_sum.real(0.0);
|
||||
m_sum.imag(0.0);
|
||||
}
|
||||
|
||||
float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 1.0;
|
||||
fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay());
|
||||
m_audioActive = delayedSample.real() != 0.0;
|
||||
|
||||
// Prevent overload based on squared magnitude variation
|
||||
// Only if AGC is active
|
||||
if (m_agcActive && m_agcClamping && (agcVal > 100.0 || agcVal == 0.0))
|
||||
{
|
||||
// qDebug("WDSPRxSink::processOneSample: %f", agcVal);
|
||||
m_agc.reset(m_agcTarget*m_agcTarget);
|
||||
m_squelchDelayLine.write(fftfilt::cmplx{0.0, 0.0});
|
||||
}
|
||||
else
|
||||
{
|
||||
m_squelchDelayLine.write(sideband[i]*agcVal);
|
||||
}
|
||||
|
||||
if (m_audioMute)
|
||||
{
|
||||
m_audioBuffer[m_audioBufferFill].r = 0;
|
||||
m_audioBuffer[m_audioBufferFill].l = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fftfilt::cmplx z = (m_agcActive && m_agcClamping) ?
|
||||
fftfilt::cmplx{m_lowpassI.filter(delayedSample.real()), m_lowpassQ.filter(delayedSample.imag())}
|
||||
: delayedSample;
|
||||
|
||||
if (m_audioBinaual)
|
||||
{
|
||||
if (m_audioFlipChannels)
|
||||
if (m_audioBinaual)
|
||||
{
|
||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(z.imag() * m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(z.real() * m_volume);
|
||||
m_demodBuffer[m_demodBufferFill++] = zr * m_volume;
|
||||
m_demodBuffer[m_demodBufferFill++] = zi * m_volume;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(z.real() * m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(z.imag() * m_volume);
|
||||
Real demod = (zr + zi) * 0.7;
|
||||
qint16 sample = (qint16)(demod * m_volume);
|
||||
m_demodBuffer[m_demodBufferFill++] = sample;
|
||||
}
|
||||
|
||||
m_demodBuffer[m_demodBufferFill++] = z.real();
|
||||
m_demodBuffer[m_demodBufferFill++] = z.imag();
|
||||
}
|
||||
else
|
||||
{
|
||||
Real demod = (z.real() + z.imag()) * 0.7;
|
||||
qint16 sample = (qint16)(demod * m_volume);
|
||||
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||
m_demodBuffer[m_demodBufferFill++] = (z.real() + z.imag()) * 0.7;
|
||||
}
|
||||
|
||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||
{
|
||||
QList<ObjectPipe*> dataPipes;
|
||||
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
|
||||
|
||||
if (dataPipes.size() > 0)
|
||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||
{
|
||||
QList<ObjectPipe*>::iterator it = dataPipes.begin();
|
||||
QList<ObjectPipe*> dataPipes;
|
||||
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
|
||||
|
||||
for (; it != dataPipes.end(); ++it)
|
||||
if (dataPipes.size() > 0)
|
||||
{
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
|
||||
QList<ObjectPipe*>::iterator it = dataPipes.begin();
|
||||
|
||||
if (fifo)
|
||||
for (; it != dataPipes.end(); ++it)
|
||||
{
|
||||
fifo->write(
|
||||
(quint8*) &m_demodBuffer[0],
|
||||
m_demodBuffer.size() * sizeof(qint16),
|
||||
m_audioBinaual ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
|
||||
);
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
|
||||
|
||||
if (fifo)
|
||||
{
|
||||
fifo->write(
|
||||
(quint8*) &m_demodBuffer[0],
|
||||
m_demodBuffer.size() * sizeof(qint16),
|
||||
m_audioBinaual ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_demodBufferFill = 0;
|
||||
}
|
||||
} // audio sample
|
||||
|
||||
if (++m_audioBufferFill == m_audioBuffer.size())
|
||||
{
|
||||
std::size_t res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], std::min(m_audioBufferFill, m_audioBuffer.size()));
|
||||
|
||||
if (res != m_audioBufferFill) {
|
||||
qDebug("WDSPRxSink::processOneSample: %lu/%lu samples written", res, m_audioBufferFill);
|
||||
}
|
||||
|
||||
m_demodBufferFill = 0;
|
||||
m_audioBufferFill = 0;
|
||||
}
|
||||
}
|
||||
} // result loop
|
||||
|
||||
++m_audioBufferFill;
|
||||
|
||||
if (m_audioBufferFill >= m_audioBuffer.size())
|
||||
if (m_spectrumSink && (m_sampleBuffer.size() != 0))
|
||||
{
|
||||
std::size_t res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], std::min(m_audioBufferFill, m_audioBuffer.size()));
|
||||
|
||||
if (res != m_audioBufferFill) {
|
||||
qDebug("WDSPRxSink::processOneSample: %lu/%lu samples written", res, m_audioBufferFill);
|
||||
}
|
||||
|
||||
m_audioBufferFill = 0;
|
||||
m_spectrumSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), false);
|
||||
m_sampleBuffer.clear();
|
||||
}
|
||||
|
||||
m_inCount = 0;
|
||||
}
|
||||
|
||||
if (m_spectrumSink && (m_sampleBuffer.size() != 0))
|
||||
{
|
||||
m_spectrumSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_dsb);
|
||||
m_sampleBuffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void WDSPRxSink::setDNR(bool dnr)
|
||||
{
|
||||
SSBFilter->setDNR(dnr);
|
||||
}
|
||||
|
||||
void WDSPRxSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
|
||||
@ -317,28 +271,6 @@ void WDSPRxSink::applyAudioSampleRate(int sampleRate)
|
||||
|
||||
WDSP::RXA::setOutputSamplerate(m_rxa, sampleRate);
|
||||
|
||||
SSBFilter->create_filter(m_LowCutoff / (float) sampleRate, m_Bandwidth / (float) sampleRate, m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow);
|
||||
DSBFilter->create_dsb_filter(m_Bandwidth / (float) sampleRate, m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow);
|
||||
|
||||
m_lowpassI.create(101, sampleRate, m_Bandwidth * 1.2);
|
||||
m_lowpassQ.create(101, sampleRate, m_Bandwidth * 1.2);
|
||||
|
||||
int agcNbSamples = (sampleRate / 1000) * (1<<m_settings.m_agcTimeLog2);
|
||||
int agcThresholdGate = (sampleRate / 1000) * m_settings.m_agcThresholdGate; // ms
|
||||
|
||||
if (m_agcNbSamples != agcNbSamples)
|
||||
{
|
||||
m_agc.resize(agcNbSamples, agcNbSamples/2, m_agcTarget);
|
||||
m_agc.setStepDownDelay(agcNbSamples);
|
||||
m_agcNbSamples = agcNbSamples;
|
||||
}
|
||||
|
||||
if (m_agcThresholdGate != agcThresholdGate)
|
||||
{
|
||||
m_agc.setGate(agcThresholdGate);
|
||||
m_agcThresholdGate = agcThresholdGate;
|
||||
}
|
||||
|
||||
m_audioFifo.setSize(sampleRate);
|
||||
m_audioSampleRate = sampleRate;
|
||||
m_audioBuffer.resize(sampleRate / 10);
|
||||
@ -367,8 +299,8 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
qDebug() << "WDSPRxSink::applySettings:"
|
||||
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
|
||||
<< " m_filterIndex: " << settings.m_filterIndex
|
||||
<< " [m_spanLog2: " << settings.m_filterBank[settings.m_filterIndex].m_spanLog2
|
||||
<< " m_rfBandwidth: " << settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth
|
||||
<< " m_spanLog2: " << settings.m_filterBank[settings.m_filterIndex].m_spanLog2
|
||||
<< " m_highCutoff: " << settings.m_filterBank[settings.m_filterIndex].m_highCutoff
|
||||
<< " m_lowCutoff: " << settings.m_filterBank[settings.m_filterIndex].m_lowCutoff
|
||||
<< " m_fftWindow: " << settings.m_filterBank[settings.m_filterIndex].m_fftWindow << "]"
|
||||
<< " m_volume: " << settings.m_volume
|
||||
@ -377,16 +309,10 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
<< " m_dsb: " << settings.m_dsb
|
||||
<< " m_audioMute: " << settings.m_audioMute
|
||||
<< " m_agcActive: " << settings.m_agc
|
||||
<< " m_agcClamping: " << settings.m_agcClamping
|
||||
<< " m_agcTimeLog2: " << settings.m_agcTimeLog2
|
||||
<< " agcPowerThreshold: " << settings.m_agcPowerThreshold
|
||||
<< " agcThresholdGate: " << settings.m_agcThresholdGate
|
||||
<< " m_dnr: " << settings.m_dnr
|
||||
<< " m_dnrScheme: " << settings.m_dnrScheme
|
||||
<< " m_dnrAboveAvgFactor: " << settings.m_dnrAboveAvgFactor
|
||||
<< " m_dnrSigmaFactor: " << settings.m_dnrSigmaFactor
|
||||
<< " m_dnrNbPeaks: " << settings.m_dnrNbPeaks
|
||||
<< " m_dnrAlpha: " << settings.m_dnrAlpha
|
||||
<< " m_agcMode: " << settings.m_agcMode
|
||||
<< " m_agcGain: " << settings.m_agcGain
|
||||
<< " m_agcSlope: " << settings.m_agcSlope
|
||||
<< " m_agcHangThreshold: " << settings.m_agcHangThreshold
|
||||
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||
<< " m_streamIndex: " << settings.m_streamIndex
|
||||
<< " m_useReverseAPI: " << settings.m_useReverseAPI
|
||||
@ -396,40 +322,79 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
<< " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
|
||||
<< " force: " << force;
|
||||
|
||||
if((m_settings.m_filterBank[m_settings.m_filterIndex].m_rfBandwidth != settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth) ||
|
||||
if((m_settings.m_filterBank[m_settings.m_filterIndex].m_highCutoff != settings.m_filterBank[settings.m_filterIndex].m_highCutoff) ||
|
||||
(m_settings.m_filterBank[m_settings.m_filterIndex].m_lowCutoff != settings.m_filterBank[settings.m_filterIndex].m_lowCutoff) ||
|
||||
(m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow != settings.m_filterBank[settings.m_filterIndex].m_fftWindow) || force)
|
||||
(m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow != settings.m_filterBank[settings.m_filterIndex].m_fftWindow) ||
|
||||
(m_settings.m_dsb != settings.m_dsb) || force)
|
||||
{
|
||||
float band, lowCutoff;
|
||||
float band, low, high, fLow, fHigh;
|
||||
|
||||
band = settings.m_filterBank[settings.m_filterIndex].m_rfBandwidth;
|
||||
lowCutoff = settings.m_filterBank[settings.m_filterIndex].m_lowCutoff;
|
||||
band = settings.m_filterBank[settings.m_filterIndex].m_highCutoff;
|
||||
high = band;
|
||||
low = settings.m_filterBank[settings.m_filterIndex].m_lowCutoff;
|
||||
|
||||
if (band < 0) {
|
||||
if (band < 0)
|
||||
{
|
||||
band = -band;
|
||||
lowCutoff = -lowCutoff;
|
||||
m_usb = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_usb = true;
|
||||
}
|
||||
|
||||
if (band < 100.0f)
|
||||
{
|
||||
band = 100.0f;
|
||||
lowCutoff = 0;
|
||||
}
|
||||
|
||||
m_Bandwidth = band;
|
||||
m_LowCutoff = lowCutoff;
|
||||
|
||||
if (high < low)
|
||||
{
|
||||
if (settings.m_dsb)
|
||||
{
|
||||
fLow = high;
|
||||
fHigh = -high;
|
||||
}
|
||||
else
|
||||
{
|
||||
fLow = high;
|
||||
fHigh = low;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings.m_dsb)
|
||||
{
|
||||
fLow = -high;
|
||||
fHigh = high;
|
||||
}
|
||||
else
|
||||
{
|
||||
fLow = low;
|
||||
fHigh = high;
|
||||
}
|
||||
}
|
||||
|
||||
Real interpolatorBandwidth = (m_Bandwidth * 1.5f) > m_channelSampleRate ? m_channelSampleRate : (m_Bandwidth * 1.5f);
|
||||
m_interpolator.create(16, m_channelSampleRate, interpolatorBandwidth, 2.0f);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) m_audioSampleRate;
|
||||
SSBFilter->create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate, settings.m_filterBank[settings.m_filterIndex].m_fftWindow);
|
||||
DSBFilter->create_dsb_filter(m_Bandwidth / (float) m_audioSampleRate, settings.m_filterBank[settings.m_filterIndex].m_fftWindow);
|
||||
m_lowpassI.create(101, m_audioSampleRate, m_Bandwidth * 1.2);
|
||||
m_lowpassQ.create(101, m_audioSampleRate, m_Bandwidth * 1.2);
|
||||
|
||||
WDSP::RXA::SetPassband(*m_rxa, fLow, fHigh);
|
||||
WDSP::NBP::NBPSetWindow(*m_rxa, m_settings.m_filterBank[m_settings.m_filterIndex].m_fftWindow);
|
||||
}
|
||||
|
||||
if ((m_settings.m_agc != settings.m_agc)
|
||||
|| (m_settings.m_agcMode != settings.m_agcMode)
|
||||
|| (m_settings.m_agcGain != settings.m_agcGain) || force)
|
||||
{
|
||||
if (settings.m_agc)
|
||||
{
|
||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, (int) settings.m_agcMode + 1);
|
||||
WDSP::WCPAGC::SetAGCFixed(*m_rxa, (double) settings.m_agcGain);
|
||||
}
|
||||
else
|
||||
{
|
||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 0);
|
||||
WDSP::WCPAGC::SetAGCTop(*m_rxa, (double) settings.m_agcGain);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_settings.m_volume != settings.m_volume) || force)
|
||||
@ -438,75 +403,15 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
m_volume /= 4.0; // for 3276.8
|
||||
}
|
||||
|
||||
if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) ||
|
||||
(m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) ||
|
||||
(m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) ||
|
||||
(m_settings.m_agcClamping != settings.m_agcClamping) || force)
|
||||
{
|
||||
int agcNbSamples = (m_audioSampleRate / 1000) * (1<<settings.m_agcTimeLog2);
|
||||
m_agc.setThresholdEnable(settings.m_agcPowerThreshold != -WDSPRxSettings::m_minPowerThresholdDB);
|
||||
double agcPowerThreshold = CalcDb::powerFromdB(settings.m_agcPowerThreshold) * (SDR_RX_SCALED*SDR_RX_SCALED);
|
||||
int agcThresholdGate = (m_audioSampleRate / 1000) * settings.m_agcThresholdGate; // ms
|
||||
bool agcClamping = settings.m_agcClamping;
|
||||
|
||||
if (m_agcNbSamples != agcNbSamples)
|
||||
{
|
||||
m_agc.resize(agcNbSamples, agcNbSamples/2, m_agcTarget);
|
||||
m_agc.setStepDownDelay(agcNbSamples);
|
||||
m_agcNbSamples = agcNbSamples;
|
||||
}
|
||||
|
||||
if (m_agcPowerThreshold != agcPowerThreshold)
|
||||
{
|
||||
m_agc.setThreshold(agcPowerThreshold);
|
||||
m_agcPowerThreshold = agcPowerThreshold;
|
||||
}
|
||||
|
||||
if (m_agcThresholdGate != agcThresholdGate)
|
||||
{
|
||||
m_agc.setGate(agcThresholdGate);
|
||||
m_agcThresholdGate = agcThresholdGate;
|
||||
}
|
||||
|
||||
if (m_agcClamping != agcClamping)
|
||||
{
|
||||
m_agcClamping = agcClamping;
|
||||
}
|
||||
|
||||
qDebug() << "WDSPRxSink::applySettings: AGC:"
|
||||
<< " agcNbSamples: " << agcNbSamples
|
||||
<< " agcPowerThreshold: " << agcPowerThreshold
|
||||
<< " agcThresholdGate: " << agcThresholdGate
|
||||
<< " agcClamping: " << agcClamping;
|
||||
if ((m_settings.m_audioBinaural != settings.m_audioBinaural) || force) {
|
||||
WDSP::PANEL::SetPanelBinaural(*m_rxa, settings.m_audioBinaural ? 1 : 0);
|
||||
}
|
||||
|
||||
if ((m_settings.m_dnr != settings.m_dnr) || force) {
|
||||
setDNR(settings.m_dnr);
|
||||
if ((m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force) {
|
||||
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0);
|
||||
}
|
||||
|
||||
if ((m_settings.m_dnrScheme != settings.m_dnrScheme) || force) {
|
||||
SSBFilter->setDNRScheme((FFTNoiseReduction::Scheme) settings.m_dnrScheme);
|
||||
}
|
||||
|
||||
if ((m_settings.m_dnrAboveAvgFactor != settings.m_dnrAboveAvgFactor) || force) {
|
||||
SSBFilter->setDNRAboveAvgFactor(settings.m_dnrAboveAvgFactor);
|
||||
}
|
||||
|
||||
if ((m_settings.m_dnrSigmaFactor != settings.m_dnrSigmaFactor) || force) {
|
||||
SSBFilter->setDNRSigmaFactor(settings.m_dnrSigmaFactor);
|
||||
}
|
||||
|
||||
if ((m_settings.m_dnrNbPeaks != settings.m_dnrNbPeaks) || force) {
|
||||
SSBFilter->setDNRNbPeaks(settings.m_dnrNbPeaks);
|
||||
}
|
||||
|
||||
if ((m_settings.m_dnrAlpha != settings.m_dnrAlpha) || force) {
|
||||
SSBFilter->setDNRAlpha(settings.m_dnrAlpha);
|
||||
}
|
||||
|
||||
m_spanLog2 = settings.m_filterBank[settings.m_filterIndex].m_spanLog2;
|
||||
m_audioBinaual = settings.m_audioBinaural;
|
||||
m_audioFlipChannels = settings.m_audioFlipChannels;
|
||||
m_dsb = settings.m_dsb;
|
||||
m_audioMute = settings.m_audioMute;
|
||||
m_agcActive = settings.m_agc;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "dsp/firfilter.h"
|
||||
#include "audio/audiofifo.h"
|
||||
#include "util/doublebufferfifo.h"
|
||||
#include "bufferprobe.hpp"
|
||||
|
||||
#include "wdsprxsettings.h"
|
||||
|
||||
@ -51,31 +52,22 @@ public:
|
||||
void applyAudioSampleRate(int sampleRate);
|
||||
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
double getMagSq() const { return m_sAvg; }
|
||||
bool getAudioActive() const { return m_audioActive; }
|
||||
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||
void setAudioFifoLabel(const QString& label) { m_audioFifo.setLabel(label); }
|
||||
void setDNR(bool dnr);
|
||||
|
||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
|
||||
{
|
||||
if (m_magsqCount > 0)
|
||||
{
|
||||
m_magsq = m_magsqSum / m_magsqCount;
|
||||
m_magSqLevelStore.m_magsq = m_magsq;
|
||||
m_magSqLevelStore.m_magsqPeak = m_magsqPeak;
|
||||
}
|
||||
|
||||
avg = m_magSqLevelStore.m_magsq;
|
||||
peak = m_magSqLevelStore.m_magsqPeak;
|
||||
nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount;
|
||||
|
||||
m_magsqSum = 0.0f;
|
||||
m_magsqPeak = 0.0f;
|
||||
m_magsqCount = 0;
|
||||
}
|
||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples);
|
||||
|
||||
private:
|
||||
class SpectrumProbe : public WDSP::BufferProbe
|
||||
{
|
||||
public:
|
||||
SpectrumProbe(SampleVector& sampleVector);
|
||||
virtual void proceed(const double *in, int nbSamples);
|
||||
private:
|
||||
SampleVector& m_sampleVector;
|
||||
};
|
||||
|
||||
struct MagSqLevelsStore
|
||||
{
|
||||
MagSqLevelsStore() :
|
||||
@ -90,23 +82,18 @@ private:
|
||||
ChannelAPI *m_channel;
|
||||
|
||||
Real m_Bandwidth;
|
||||
Real m_LowCutoff;
|
||||
Real m_volume;
|
||||
int m_spanLog2;
|
||||
fftfilt::cmplx m_sum;
|
||||
int m_undersampleCount;
|
||||
int m_channelSampleRate;
|
||||
int m_channelFrequencyOffset;
|
||||
bool m_audioBinaual;
|
||||
bool m_audioFlipChannels;
|
||||
bool m_usb;
|
||||
bool m_dsb;
|
||||
bool m_audioMute;
|
||||
double m_magsq;
|
||||
double m_magsqSum;
|
||||
double m_magsqPeak;
|
||||
int m_magsqCount;
|
||||
MagSqLevelsStore m_magSqLevelStore;
|
||||
double m_sAvg;
|
||||
double m_sPeak;
|
||||
int m_sCount;
|
||||
MagAGC m_agc;
|
||||
bool m_agcActive;
|
||||
bool m_agcClamping;
|
||||
@ -115,19 +102,18 @@ private:
|
||||
int m_agcThresholdGate; //!< Gate length in number of samples befor threshold triggers
|
||||
DoubleBufferFIFO<fftfilt::cmplx> m_squelchDelayLine;
|
||||
bool m_audioActive; //!< True if an audio signal is produced (no AGC or AGC and above threshold)
|
||||
Lowpass<Real> m_lowpassI;
|
||||
Lowpass<Real> m_lowpassQ;
|
||||
|
||||
|
||||
NCOF m_nco;
|
||||
Interpolator m_interpolator;
|
||||
Real m_interpolatorDistance;
|
||||
Real m_interpolatorDistanceRemain;
|
||||
fftfilt* SSBFilter;
|
||||
fftfilt* DSBFilter;
|
||||
// fftfilt* SSBFilter;
|
||||
// fftfilt* DSBFilter;
|
||||
|
||||
SpectrumVis* m_spectrumSink;
|
||||
SampleVector m_sampleBuffer;
|
||||
SpectrumProbe m_spectrumProbe;
|
||||
int m_inCount;
|
||||
|
||||
AudioVector m_audioBuffer;
|
||||
std::size_t m_audioBufferFill;
|
||||
|
@ -59,6 +59,7 @@ set(wdsp_HEADERS
|
||||
bandpass.hpp
|
||||
bldr.hpp
|
||||
bps.hpp
|
||||
bufferprobe.hpp
|
||||
calculus.hpp
|
||||
cblock.hpp
|
||||
cfcomp.hpp
|
||||
@ -132,4 +133,3 @@ if (LINUX)
|
||||
)
|
||||
install(TARGETS wdsp_make_interface wdsp_make_calculus DESTINATION ${INSTALL_BIN_DIR})
|
||||
endif()
|
||||
|
||||
|
657
wdsp/RXA.cpp
657
wdsp/RXA.cpp
@ -84,454 +84,456 @@ RXA* RXA::create_rxa (
|
||||
rxa->outbuff = new double[1 * rxa->dsp_outsize * 2]; // (double *) malloc0 (1 * ch.dsp_outsize * sizeof (complex));
|
||||
rxa->midbuff = new double[2 * rxa->dsp_size * 2]; // (double *) malloc0 (2 * ch.dsp_size * sizeof (complex));
|
||||
|
||||
// shift to select a slice of spectrum
|
||||
// Ftequency shifter - shift to select a slice of spectrum
|
||||
rxa->shift.p = SHIFT::create_shift (
|
||||
1, // run
|
||||
rxa->dsp_insize, // input buffer size
|
||||
1, // run
|
||||
rxa->dsp_insize, // input buffer size
|
||||
rxa->inbuff, // pointer to input buffer
|
||||
rxa->inbuff, // pointer to output buffer
|
||||
rxa->in_rate, // samplerate
|
||||
0.0); // amount to shift (Hz)
|
||||
rxa->in_rate, // samplerate
|
||||
0.0); // amount to shift (Hz)
|
||||
|
||||
// resample to dsp rate for main processing
|
||||
// Input resampler - resample to dsp rate for main processing
|
||||
rxa->rsmpin.p = RESAMPLE::create_resample (
|
||||
0, // run - will be turned ON below if needed
|
||||
rxa->dsp_insize, // input buffer size
|
||||
0, // run - will be turned ON below if needed
|
||||
rxa->dsp_insize, // input buffer size
|
||||
rxa->inbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
rxa->in_rate, // input samplerate
|
||||
rxa->dsp_rate, // output samplerate
|
||||
0.0, // select cutoff automatically
|
||||
0, // select ncoef automatically
|
||||
1.0); // gain
|
||||
rxa->in_rate, // input samplerate
|
||||
rxa->dsp_rate, // output samplerate
|
||||
0.0, // select cutoff automatically
|
||||
0, // select ncoef automatically
|
||||
1.0); // gain
|
||||
|
||||
// signal generator
|
||||
// Signal generator
|
||||
rxa->gen0.p = GEN::create_gen (
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // input buffer
|
||||
rxa->midbuff, // output buffer
|
||||
rxa->dsp_rate, // sample rate
|
||||
2); // mode
|
||||
rxa->dsp_rate, // sample rate
|
||||
2); // mode
|
||||
|
||||
// adc (input) meter
|
||||
// Input meter - ADC
|
||||
rxa->adcmeter.p = METER::create_meter (
|
||||
1, // run
|
||||
0, // optional pointer to another 'run'
|
||||
rxa->dsp_size, // size
|
||||
0, // run
|
||||
0, // optional pointer to another 'run'
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to buffer
|
||||
rxa->dsp_rate, // samplerate
|
||||
0.100, // averaging time constant
|
||||
0.100, // peak decay time constant
|
||||
rxa->dsp_rate, // samplerate
|
||||
0.100, // averaging time constant
|
||||
0.100, // peak decay time constant
|
||||
rxa->meter, // result vector
|
||||
rxa->pmtupdate, // locks for meter access
|
||||
RXA_ADC_AV, // index for average value
|
||||
RXA_ADC_PK, // index for peak value
|
||||
-1, // index for gain value
|
||||
0); // pointer for gain computation
|
||||
RXA_ADC_AV, // index for average value
|
||||
RXA_ADC_PK, // index for peak value
|
||||
-1, // index for gain value
|
||||
0); // pointer for gain computation
|
||||
|
||||
// Notched bandpass section
|
||||
|
||||
// notch database
|
||||
rxa->ndb.p = NOTCHDB::create_notchdb (
|
||||
0, // master run for all nbp's
|
||||
1024); // max number of notches
|
||||
0, // master run for all nbp's
|
||||
1024); // max number of notches
|
||||
|
||||
// notched bandpass
|
||||
rxa->nbp0.p = NBP::create_nbp (
|
||||
1, // run, always runs
|
||||
0, // run the notches
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
std::max(2048, rxa->dsp_size), // number of coefficients
|
||||
0, // minimum phase flag
|
||||
1, // run, always runs
|
||||
0, // run the notches
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
std::max(2048, rxa->dsp_size), // number of coefficients
|
||||
0, // minimum phase flag
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
-4150.0, // lower filter frequency
|
||||
-150.0, // upper filter frequency
|
||||
rxa->dsp_rate, // sample rate
|
||||
0, // wintype
|
||||
1.0, // gain
|
||||
1, // auto-increase notch width
|
||||
1025, // max number of passbands
|
||||
rxa->ndb.p); // addr of database pointer
|
||||
-4150.0, // lower filter frequency
|
||||
-150.0, // upper filter frequency
|
||||
rxa->dsp_rate, // sample rate
|
||||
0, // wintype
|
||||
1.0, // gain
|
||||
1, // auto-increase notch width
|
||||
1025, // max number of passbands
|
||||
rxa->ndb.p); // addr of database pointer
|
||||
|
||||
// bandpass for snba
|
||||
rxa->bpsnba.p = BPSNBA::create_bpsnba (
|
||||
0, // bpsnba run flag
|
||||
0, // run the notches
|
||||
0, // position
|
||||
rxa->dsp_size, // size
|
||||
std::max(2048, rxa->dsp_size), // number of filter coefficients
|
||||
0, // minimum phase flag
|
||||
0, // bpsnba run flag
|
||||
0, // run the notches
|
||||
0, // position
|
||||
rxa->dsp_size, // size
|
||||
std::max(2048, rxa->dsp_size), // number of filter coefficients
|
||||
0, // minimum phase flag
|
||||
rxa->midbuff, // input buffer
|
||||
rxa->midbuff, // output buffer
|
||||
rxa->dsp_rate, // samplerate
|
||||
+ 250.0, // abs value of cutoff nearest zero
|
||||
+ 5700.0, // abs value of cutoff farthest zero
|
||||
- 5700.0, // current low frequency
|
||||
- 250.0, // current high frequency
|
||||
0, // wintype
|
||||
1.0, // gain
|
||||
1, // auto-increase notch width
|
||||
1025, // max number of passbands
|
||||
rxa->dsp_rate, // samplerate
|
||||
+ 250.0, // abs value of cutoff nearest zero
|
||||
+ 5700.0, // abs value of cutoff farthest zero
|
||||
- 5700.0, // current low frequency
|
||||
- 250.0, // current high frequency
|
||||
0, // wintype
|
||||
1.0, // gain
|
||||
1, // auto-increase notch width
|
||||
1025, // max number of passbands
|
||||
rxa->ndb.p); // addr of database pointer
|
||||
|
||||
// send spectrum display
|
||||
// Post filter display send - send spectrum display (after S-meter in the block diagram)
|
||||
rxa->sender.p = SENDER::create_sender (
|
||||
0, // run
|
||||
0, // flag
|
||||
0, // mode
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
0, // arg0 <- disp
|
||||
1, // arg1 <- ss
|
||||
0, // arg2 <- LO
|
||||
0); // arg3 <- NOT USED
|
||||
0, // flag
|
||||
0, // mode
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff // pointer to input buffer
|
||||
);
|
||||
|
||||
// End notched bandpass section
|
||||
|
||||
// S-meter
|
||||
rxa->smeter.p = METER::create_meter (
|
||||
1, // run
|
||||
0, // optional pointer to another 'run'
|
||||
rxa->dsp_size, // size
|
||||
1, // run
|
||||
0, // optional pointer to another 'run'
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to buffer
|
||||
rxa->dsp_rate, // samplerate
|
||||
0.100, // averaging time constant
|
||||
0.100, // peak decay time constant
|
||||
rxa->dsp_rate, // samplerate
|
||||
0.100, // averaging time constant
|
||||
0.100, // peak decay time constant
|
||||
rxa->meter, // result vector
|
||||
rxa->pmtupdate, // locks for meter access
|
||||
RXA_S_AV, // index for average value
|
||||
RXA_S_PK, // index for peak value
|
||||
-1, // index for gain value
|
||||
0); // pointer for gain computation
|
||||
RXA_S_AV, // index for average value
|
||||
RXA_S_PK, // index for peak value
|
||||
-1, // index for gain value
|
||||
0); // pointer for gain computation
|
||||
|
||||
// AM squelch
|
||||
// AM squelch capture (for other modes than FM)
|
||||
rxa->amsq.p = AMSQ::create_amsq (
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to signal input buffer used by xamsq
|
||||
rxa->midbuff, // pointer to signal output buffer used by xamsq
|
||||
rxa->midbuff, // pointer to trigger buffer that xamsqcap will capture
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.010, // time constant for averaging signal level
|
||||
0.070, // signal up transition time
|
||||
0.070, // signal down transition time
|
||||
0.009, // signal level to initiate tail
|
||||
0.010, // signal level to initiate unmute
|
||||
0.000, // minimum tail length
|
||||
1.500, // maximum tail length
|
||||
0.0); // muted gain
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.010, // time constant for averaging signal level
|
||||
0.070, // signal up transition time
|
||||
0.070, // signal down transition time
|
||||
0.009, // signal level to initiate tail
|
||||
0.010, // signal level to initiate unmute
|
||||
0.000, // minimum tail length
|
||||
1.500, // maximum tail length
|
||||
0.0); // muted gain
|
||||
|
||||
// AM demod
|
||||
// AM/SAM demodulator
|
||||
rxa->amd.p = AMD::create_amd (
|
||||
0, // run - OFF by default
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run - OFF by default
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
0, // mode: 0->AM, 1->SAM
|
||||
1, // levelfade: 0->OFF, 1->ON
|
||||
0, // sideband mode: 0->OFF
|
||||
rxa->dsp_rate, // sample rate
|
||||
-2000.0, // minimum lock frequency
|
||||
+2000.0, // maximum lock frequency
|
||||
1.0, // zeta
|
||||
250.0, // omegaN
|
||||
0.02, // tauR
|
||||
1.4); // tauI
|
||||
0, // mode: 0->AM, 1->SAM
|
||||
1, // levelfade: 0->OFF, 1->ON
|
||||
0, // sideband mode: 0->OFF
|
||||
rxa->dsp_rate, // sample rate
|
||||
-2000.0, // minimum lock frequency
|
||||
+2000.0, // maximum lock frequency
|
||||
1.0, // zeta
|
||||
250.0, // omegaN
|
||||
0.02, // tauR
|
||||
1.4); // tauI
|
||||
|
||||
// FM demod
|
||||
// FM demodulator
|
||||
rxa->fmd.p = FMD::create_fmd (
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
rxa->dsp_rate, // sample rate
|
||||
5000.0, // deviation
|
||||
300.0, // f_low
|
||||
3000.0, // f_high
|
||||
-8000.0, // fmin
|
||||
+8000.0, // fmax
|
||||
1.0, // zeta
|
||||
20000.0, // omegaN
|
||||
0.02, // tau - for dc removal
|
||||
0.5, // audio gain
|
||||
1, // run tone filter
|
||||
254.1, // ctcss frequency
|
||||
std::max(2048, rxa->dsp_size), // # coefs for de-emphasis filter
|
||||
0, // min phase flag for de-emphasis filter
|
||||
std::max(2048, rxa->dsp_size), // # coefs for audio cutoff filter
|
||||
0); // min phase flag for audio cutoff filter
|
||||
rxa->dsp_rate, // sample rate
|
||||
5000.0, // deviation
|
||||
300.0, // f_low
|
||||
3000.0, // f_high
|
||||
-8000.0, // fmin
|
||||
+8000.0, // fmax
|
||||
1.0, // zeta
|
||||
20000.0, // omegaN
|
||||
0.02, // tau - for dc removal
|
||||
0.5, // audio gain
|
||||
1, // run tone filter
|
||||
254.1, // ctcss frequency
|
||||
std::max(2048, rxa->dsp_size), // # coefs for de-emphasis filter
|
||||
0, // min phase flag for de-emphasis filter
|
||||
std::max(2048, rxa->dsp_size), // # coefs for audio cutoff filter
|
||||
0); // min phase flag for audio cutoff filter
|
||||
|
||||
// FM squelch
|
||||
// FM squelch apply
|
||||
rxa->fmsq.p = FMSQ::create_fmsq (
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to input signal buffer
|
||||
rxa->midbuff, // pointer to output signal buffer
|
||||
rxa->fmd.p->audio, // pointer to trigger buffer
|
||||
rxa->dsp_rate, // sample rate
|
||||
5000.0, // cutoff freq for noise filter (Hz)
|
||||
rxa->dsp_rate, // sample rate
|
||||
5000.0, // cutoff freq for noise filter (Hz)
|
||||
&rxa->fmd.p->pllpole, // pointer to pole frequency of the fmd pll (Hz)
|
||||
0.100, // delay time after channel flush
|
||||
0.001, // tau for noise averaging
|
||||
0.100, // tau for long noise averaging
|
||||
0.050, // signal up transition time
|
||||
0.010, // signal down transition time
|
||||
0.750, // noise level to initiate tail
|
||||
0.562, // noise level to initiate unmute
|
||||
0.000, // minimum tail time
|
||||
1.200, // maximum tail time
|
||||
std::max(2048, rxa->dsp_size), // number of coefficients for noise filter
|
||||
0); // minimum phase flag
|
||||
0.100, // delay time after channel flush
|
||||
0.001, // tau for noise averaging
|
||||
0.100, // tau for long noise averaging
|
||||
0.050, // signal up transition time
|
||||
0.010, // signal down transition time
|
||||
0.750, // noise level to initiate tail
|
||||
0.562, // noise level to initiate unmute
|
||||
0.000, // minimum tail time
|
||||
1.200, // maximum tail time
|
||||
std::max(2048, rxa->dsp_size), // number of coefficients for noise filter
|
||||
0); // minimum phase flag
|
||||
|
||||
// snba
|
||||
// Spectral noise blanker (SNB)
|
||||
rxa->snba.p = SNBA::create_snba (
|
||||
0, // run
|
||||
0, // run
|
||||
rxa->midbuff, // input buffer
|
||||
rxa->midbuff, // output buffer
|
||||
rxa->dsp_rate, // input / output sample rate
|
||||
12000, // internal processing sample rate
|
||||
rxa->dsp_size, // buffer size
|
||||
4, // overlap factor to use
|
||||
256, // frame size to use; sized for 12K rate
|
||||
64, // asize
|
||||
2, // npasses
|
||||
8.0, // k1
|
||||
20.0, // k2
|
||||
10, // b
|
||||
2, // pre
|
||||
2, // post
|
||||
0.5, // pmultmin
|
||||
200.0, // output resampler low cutoff
|
||||
5400.0); // output resampler high cutoff
|
||||
rxa->dsp_rate, // input / output sample rate
|
||||
12000, // internal processing sample rate
|
||||
rxa->dsp_size, // buffer size
|
||||
4, // overlap factor to use
|
||||
256, // frame size to use; sized for 12K rate
|
||||
64, // asize
|
||||
2, // npasses
|
||||
8.0, // k1
|
||||
20.0, // k2
|
||||
10, // b
|
||||
2, // pre
|
||||
2, // post
|
||||
0.5, // pmultmin
|
||||
200.0, // output resampler low cutoff
|
||||
5400.0); // output resampler high cutoff
|
||||
|
||||
// EQ
|
||||
// Equalizer
|
||||
{
|
||||
double default_F[11] = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0};
|
||||
//double default_G[11] = {0.0, -12.0, -12.0, -12.0, -1.0, +1.0, +4.0, +9.0, +12.0, -10.0, -10.0};
|
||||
double default_G[11] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
||||
rxa->eqp.p = EQP::create_eqp (
|
||||
0, // run - OFF by default
|
||||
rxa->dsp_size, // buffer size
|
||||
std::max(2048, rxa->dsp_size), // number of filter coefficients
|
||||
0, // minimum phase flag
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
10, // number of frequencies
|
||||
default_F, // frequency vector
|
||||
default_G, // gain vector
|
||||
0, // cutoff mode
|
||||
0, // wintype
|
||||
rxa->dsp_rate); // sample rate
|
||||
0, // run - OFF by default
|
||||
rxa->dsp_size, // buffer size
|
||||
std::max(2048, rxa->dsp_size), // number of filter coefficients
|
||||
0, // minimum phase flag
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
10, // number of frequencies
|
||||
default_F, // frequency vector
|
||||
default_G, // gain vector
|
||||
0, // cutoff mode
|
||||
0, // wintype
|
||||
rxa->dsp_rate); // sample rate
|
||||
}
|
||||
|
||||
// ANF
|
||||
// Auto notch filter
|
||||
rxa->anf.p = ANF::create_anf (
|
||||
0, // run - OFF by default
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run - OFF by default
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
ANF_DLINE_SIZE, // dline_size
|
||||
64, // taps
|
||||
16, // delay
|
||||
0.0001, // two_mu
|
||||
0.1, // gamma
|
||||
1.0, // lidx
|
||||
0.0, // lidx_min
|
||||
200.0, // lidx_max
|
||||
6.25e-12, // ngamma
|
||||
6.25e-10, // den_mult
|
||||
1.0, // lincr
|
||||
3.0); // ldecr
|
||||
ANF_DLINE_SIZE, // dline_size
|
||||
64, // taps
|
||||
16, // delay
|
||||
0.0001, // two_mu
|
||||
0.1, // gamma
|
||||
1.0, // lidx
|
||||
0.0, // lidx_min
|
||||
200.0, // lidx_max
|
||||
6.25e-12, // ngamma
|
||||
6.25e-10, // den_mult
|
||||
1.0, // lincr
|
||||
3.0); // ldecr
|
||||
|
||||
// ANR
|
||||
// LMS noise reduction (ANR or "NR")
|
||||
rxa->anr.p = ANR::create_anr (
|
||||
0, // run - OFF by default
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run - OFF by default
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
ANR_DLINE_SIZE, // dline_size
|
||||
64, // taps
|
||||
16, // delay
|
||||
0.0001, // two_mu
|
||||
0.1, // gamma
|
||||
120.0, // lidx
|
||||
120.0, // lidx_min
|
||||
200.0, // lidx_max
|
||||
0.001, // ngamma
|
||||
6.25e-10, // den_mult
|
||||
1.0, // lincr
|
||||
3.0); // ldecr
|
||||
ANR_DLINE_SIZE, // dline_size
|
||||
64, // taps
|
||||
16, // delay
|
||||
0.0001, // two_mu
|
||||
0.1, // gamma
|
||||
120.0, // lidx
|
||||
120.0, // lidx_min
|
||||
200.0, // lidx_max
|
||||
0.001, // ngamma
|
||||
6.25e-10, // den_mult
|
||||
1.0, // lincr
|
||||
3.0); // ldecr
|
||||
|
||||
|
||||
// EMNR
|
||||
// Spectral noise reduyction (EMNR or "NR2")
|
||||
rxa->emnr.p = EMNR::create_emnr (
|
||||
0, // run
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // input buffer
|
||||
rxa->midbuff, // output buffer
|
||||
4096, // FFT size
|
||||
4, // overlap
|
||||
rxa->dsp_rate, // samplerate
|
||||
0, // window type
|
||||
1.0, // gain
|
||||
2, // gain method
|
||||
0, // npe_method
|
||||
1); // ae_run
|
||||
4096, // FFT size
|
||||
4, // overlap
|
||||
rxa->dsp_rate, // samplerate
|
||||
0, // window type
|
||||
1.0, // gain
|
||||
2, // gain method
|
||||
0, // npe_method
|
||||
1); // ae_run
|
||||
|
||||
// AGC
|
||||
rxa->agc.p = WCPAGC::create_wcpagc (
|
||||
1, // run
|
||||
3, // mode
|
||||
1, // peakmode = envelope
|
||||
1, // run
|
||||
3, // mode
|
||||
1, // peakmode = envelope
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.001, // tau_attack
|
||||
0.250, // tau_decay
|
||||
4, // n_tau
|
||||
10000.0, // max_gain
|
||||
1.5, // var_gain
|
||||
1000.0, // fixed_gain
|
||||
1.0, // max_input
|
||||
1.0, // out_target
|
||||
0.250, // tau_fast_backaverage
|
||||
0.005, // tau_fast_decay
|
||||
5.0, // pop_ratio
|
||||
1, // hang_enable
|
||||
0.500, // tau_hang_backmult
|
||||
0.250, // hangtime
|
||||
0.250, // hang_thresh
|
||||
0.100); // tau_hang_decay
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.001, // tau_attack
|
||||
0.250, // tau_decay
|
||||
4, // n_tau
|
||||
10000.0, // max_gain
|
||||
1.5, // var_gain
|
||||
1000.0, // fixed_gain
|
||||
1.0, // max_input
|
||||
1.0, // out_target
|
||||
0.250, // tau_fast_backaverage
|
||||
0.005, // tau_fast_decay
|
||||
5.0, // pop_ratio
|
||||
1, // hang_enable
|
||||
0.500, // tau_hang_backmult
|
||||
0.250, // hangtime
|
||||
0.250, // hang_thresh
|
||||
0.100); // tau_hang_decay
|
||||
|
||||
// agc gain meter
|
||||
// AGC meter
|
||||
rxa->agcmeter.p = METER::create_meter (
|
||||
1, // run
|
||||
0, // optional pointer to another 'run'
|
||||
rxa->dsp_size, // size
|
||||
0, // run
|
||||
0, // optional pointer to another 'run'
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to buffer
|
||||
rxa->dsp_rate, // samplerate
|
||||
0.100, // averaging time constant
|
||||
0.100, // peak decay time constant
|
||||
rxa->dsp_rate, // samplerate
|
||||
0.100, // averaging time constant
|
||||
0.100, // peak decay time constant
|
||||
rxa->meter, // result vector
|
||||
rxa->pmtupdate, // locks for meter access
|
||||
RXA_AGC_AV, // index for average value
|
||||
RXA_AGC_PK, // index for peak value
|
||||
RXA_AGC_GAIN, // index for gain value
|
||||
RXA_AGC_AV, // index for average value
|
||||
RXA_AGC_PK, // index for peak value
|
||||
RXA_AGC_GAIN, // index for gain value
|
||||
&rxa->agc.p->gain); // pointer for gain computation
|
||||
|
||||
// bandpass filter
|
||||
// Bandpass filter - After spectral noise reduction in the block diagram
|
||||
rxa->bp1.p = BANDPASS::create_bandpass (
|
||||
1, // run - used only with ( AM || ANF || ANR || EMNR)
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
std::max(2048, rxa->dsp_size), // number of coefficients
|
||||
0, // flag for minimum phase
|
||||
1, // run - used only with ( AM || ANF || ANR || EMNR)
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
std::max(2048, rxa->dsp_size), // number of coefficients
|
||||
0, // flag for minimum phase
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
-4150.0, // lower filter frequency
|
||||
-150.0, // upper filter frequency
|
||||
rxa->dsp_rate, // sample rate
|
||||
1, // wintype
|
||||
1.0); // gain
|
||||
-4150.0, // lower filter frequency
|
||||
-150.0, // upper filter frequency
|
||||
rxa->dsp_rate, // sample rate
|
||||
1, // wintype
|
||||
1.0); // gain
|
||||
|
||||
// pull phase & scope display data
|
||||
// Scope/phase display send - pull phase & scope display data
|
||||
rxa->sip1.p = SIPHON::create_siphon (
|
||||
1, // run - needed only for phase display
|
||||
0, // position
|
||||
0, // mode
|
||||
0, // disp
|
||||
rxa->dsp_size, // size of input buffer
|
||||
0, // run - needed only for phase display
|
||||
0, // position
|
||||
0, // mode
|
||||
0, // disp
|
||||
rxa->dsp_size, // size of input buffer
|
||||
rxa->midbuff, // input buffer
|
||||
4096, // number of samples to store
|
||||
4096, // fft size for spectrum
|
||||
0); // specmode
|
||||
4096, // number of samples to store
|
||||
4096, // fft size for spectrum
|
||||
0); // specmode
|
||||
|
||||
// carrier block
|
||||
// AM carrier block
|
||||
rxa->cbl.p = CBL::create_cbl (
|
||||
0, // run - needed only if set to ON
|
||||
rxa->dsp_size, // buffer size
|
||||
0, // run - needed only if set to ON
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
0, // mode
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.02); // tau
|
||||
0, // mode
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.02); // tau
|
||||
|
||||
// peaking filter
|
||||
// CW peaking filter
|
||||
rxa->speak.p = SPEAK::create_speak (
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size,
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size,
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
rxa->dsp_rate, // sample rate
|
||||
600.0, // center frequency
|
||||
100.0, // bandwidth
|
||||
2.0, // gain
|
||||
4, // number of stages
|
||||
1); // design
|
||||
rxa->dsp_rate, // sample rate
|
||||
600.0, // center frequency
|
||||
100.0, // bandwidth
|
||||
2.0, // gain
|
||||
4, // number of stages
|
||||
1); // design
|
||||
|
||||
// multiple peak filter
|
||||
// Dolly filter (multiple peak filter) - default is 2 for RTTY
|
||||
{
|
||||
int def_enable[2] = {1, 1};
|
||||
double def_freq[2] = {2125.0, 2295.0};
|
||||
double def_bw[2] = {75.0, 75.0};
|
||||
double def_gain[2] = {1.0, 1.0};
|
||||
rxa->mpeak.p = MPEAK::create_mpeak (
|
||||
0, // run
|
||||
rxa->dsp_size, // size
|
||||
0, // run
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
rxa->dsp_rate, // sample rate
|
||||
2, // number of peaking filters
|
||||
def_enable, // enable vector
|
||||
def_freq, // frequency vector
|
||||
def_bw, // bandwidth vector
|
||||
def_gain, // gain vector
|
||||
4 ); // number of stages
|
||||
rxa->dsp_rate, // sample rate
|
||||
2, // number of peaking filters
|
||||
def_enable, // enable vector
|
||||
def_freq, // frequency vector
|
||||
def_bw, // bandwidth vector
|
||||
def_gain, // gain vector
|
||||
4 ); // number of stages
|
||||
}
|
||||
|
||||
// syllabic squelch
|
||||
// Syllabic squelch (Voice suelch) - Not in the block diagram
|
||||
rxa->ssql.p = SSQL::create_ssql(
|
||||
0, // run
|
||||
rxa->dsp_size, // size
|
||||
0, // run
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.070, // signal up transition time
|
||||
0.070, // signal down transition time
|
||||
0.0, // muted gain
|
||||
0.1, // mute time-constant
|
||||
0.1, // unmute time-constant
|
||||
0.08, // window threshold
|
||||
0.8197, // trigger threshold
|
||||
2400, // ring size for f_to_v converter
|
||||
2000.0); // max freq for f_to_v converter
|
||||
rxa->dsp_rate, // sample rate
|
||||
0.070, // signal up transition time
|
||||
0.070, // signal down transition time
|
||||
0.0, // muted gain
|
||||
0.1, // mute time-constant
|
||||
0.1, // unmute time-constant
|
||||
0.08, // window threshold
|
||||
0.8197, // trigger threshold
|
||||
2400, // ring size for f_to_v converter
|
||||
2000.0); // max freq for f_to_v converter
|
||||
|
||||
// patchpanel
|
||||
// PatchPanel
|
||||
rxa->panel.p = PANEL::create_panel (
|
||||
1, // run
|
||||
rxa->dsp_size, // size
|
||||
1, // run
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->midbuff, // pointer to output buffer
|
||||
4.0, // gain1
|
||||
1.0, // gain2I
|
||||
1.0, // gain2Q
|
||||
3, // 3 for I and Q
|
||||
0); // no copy
|
||||
4.0, // gain1
|
||||
1.0, // gain2I
|
||||
1.0, // gain2Q
|
||||
3, // 3 for I and Q
|
||||
0); // no copy
|
||||
|
||||
// resample
|
||||
// AM squelch apply - absent but in the block diagram
|
||||
|
||||
// Output resampler
|
||||
rxa->rsmpout.p = RESAMPLE::create_resample (
|
||||
0, // run - will be turned ON below if needed
|
||||
rxa->dsp_size, // input buffer size
|
||||
0, // run - will be turned ON below if needed
|
||||
rxa->dsp_size, // input buffer size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
rxa->outbuff, // pointer to output buffer
|
||||
rxa->dsp_rate, // input sample rate
|
||||
rxa->out_rate, // output sample rate
|
||||
0.0, // select cutoff automatically
|
||||
0, // select ncoef automatically
|
||||
1.0); // gain
|
||||
rxa->dsp_rate, // input sample rate
|
||||
rxa->out_rate, // output sample rate
|
||||
0.0, // select cutoff automatically
|
||||
0, // select ncoef automatically
|
||||
1.0); // gain
|
||||
|
||||
// turn OFF / ON resamplers as needed
|
||||
ResCheck (*rxa);
|
||||
@ -825,6 +827,12 @@ void RXA::setDSPBuffsize (RXA *rxa, int dsp_size)
|
||||
rxa->csDSP.unlock();
|
||||
}
|
||||
|
||||
void RXA::setSpectrumProbe(BufferProbe *spectrumProbe)
|
||||
{
|
||||
SENDER::SetSpectrum(*this, 1, spectrumProbe);
|
||||
sender.p->run = 1;
|
||||
}
|
||||
|
||||
/********************************************************************************************************
|
||||
* *
|
||||
* RXA Mode & Filter Controls *
|
||||
@ -843,8 +851,8 @@ void RXA::SetMode (RXA& rxa, int mode)
|
||||
rxa.snba.p->run,
|
||||
rxa.emnr.p->run,
|
||||
rxa.anf.p->run,
|
||||
rxa.anr.p->run)
|
||||
;
|
||||
rxa.anr.p->run
|
||||
);
|
||||
rxa.csDSP.lock();
|
||||
rxa.mode = mode;
|
||||
rxa.amd.p->run = 0;
|
||||
@ -861,7 +869,6 @@ void RXA::SetMode (RXA& rxa, int mode)
|
||||
rxa.amd.p->mode = 1;
|
||||
break;
|
||||
case RXA_DSB:
|
||||
|
||||
break;
|
||||
case RXA_FM:
|
||||
rxa.fmd.p->run = 1;
|
||||
@ -1033,9 +1040,9 @@ void RXA::bpsnbaSet (RXA& rxa)
|
||||
|
||||
void RXA::SetPassband (RXA& rxa, double f_low, double f_high)
|
||||
{
|
||||
BANDPASS::SetBandpassFreqs (rxa, f_low, f_high);
|
||||
SNBA::SetSNBAOutputBandwidth (rxa, f_low, f_high);
|
||||
NBP::NBPSetFreqs (rxa, f_low, f_high);
|
||||
BANDPASS::SetBandpassFreqs (rxa, f_low, f_high); // After spectral noise reduction ( AM || ANF || ANR || EMNR)
|
||||
SNBA::SetSNBAOutputBandwidth (rxa, f_low, f_high); // Spectral noise blanker (SNB)
|
||||
NBP::NBPSetFreqs (rxa, f_low, f_high); // Notched bandpass
|
||||
}
|
||||
|
||||
void RXA::SetNC (RXA& rxa, int nc)
|
||||
|
@ -63,6 +63,7 @@ class PANEL;
|
||||
class SIPHON;
|
||||
class CBL;
|
||||
class SSQL;
|
||||
class BufferProbe;
|
||||
|
||||
class WDSP_API RXA : public Unit
|
||||
{
|
||||
@ -97,7 +98,7 @@ public:
|
||||
|
||||
int mode;
|
||||
double meter[RXA_METERTYPE_LAST];
|
||||
QRecursiveMutex* pmtupdate[RXA_METERTYPE_LAST];
|
||||
QRecursiveMutex *pmtupdate[RXA_METERTYPE_LAST];
|
||||
struct
|
||||
{
|
||||
METER *p;
|
||||
@ -216,6 +217,7 @@ public:
|
||||
int get_outsize() const { return dsp_outsize; }
|
||||
double *get_inbuff() { return inbuff; }
|
||||
double *get_outbuff() { return outbuff; }
|
||||
void setSpectrumProbe(BufferProbe *_spectrumProbe);
|
||||
static void setInputSamplerate (RXA *rxa, int in_rate);
|
||||
static void setOutputSamplerate (RXA *rxa, int out_rate);
|
||||
static void setDSPSamplerate (RXA *rxa, int dsp_rate);
|
||||
|
39
wdsp/bufferprobe.hpp
Normal file
39
wdsp/bufferprobe.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/* bufferProbe.hpp
|
||||
|
||||
This file is part of a program that implements a Software-Defined Radio.
|
||||
|
||||
Copyright (C) 2013 Warren Pratt, NR0V
|
||||
Copyright (C) 2024 Edouard Griffiths, F4EXB Adapted to SDRangel
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
The author can be reached by email at
|
||||
|
||||
warren@wpratt.com
|
||||
|
||||
This interface can be subclassed to receive complex samples from a block
|
||||
Typically spectrum samples from the sender
|
||||
|
||||
*/
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class BufferProbe
|
||||
{
|
||||
public:
|
||||
virtual void proceed(const double *buffer, int nb_samples) = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
@ -28,6 +28,8 @@ warren@wpratt.com
|
||||
#include "comm.hpp"
|
||||
#include "meterlog10.hpp"
|
||||
#include "meter.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
@ -147,16 +149,14 @@ void METER::setSize_meter (METER *a, int size)
|
||||
* *
|
||||
********************************************************************************************************/
|
||||
|
||||
// PORT
|
||||
// double GetRXAMeter (int channel, int mt)
|
||||
// {
|
||||
// double val;
|
||||
// CRITICAL_SECTION* a = rxa[channel].pmtupdate[mt];
|
||||
// EnterCriticalSection (a);
|
||||
// val = rxa[channel].meter[mt];
|
||||
// LeaveCriticalSection (a);
|
||||
// return val;
|
||||
// }
|
||||
double METER::GetMeter (RXA& rxa, int mt)
|
||||
{
|
||||
double val;
|
||||
rxa.pmtupdate[mt]->lock();
|
||||
val = rxa.meter[mt];
|
||||
rxa.pmtupdate[mt]->unlock();
|
||||
return val;
|
||||
}
|
||||
|
||||
/********************************************************************************************************
|
||||
* *
|
||||
@ -164,15 +164,13 @@ void METER::setSize_meter (METER *a, int size)
|
||||
* *
|
||||
********************************************************************************************************/
|
||||
|
||||
// PORT
|
||||
// double GetTXAMeter (int channel, int mt)
|
||||
// {
|
||||
// double val;
|
||||
// CRITICAL_SECTION* a = txa[channel].pmtupdate[mt];
|
||||
// EnterCriticalSection (a);
|
||||
// val = txa[channel].meter[mt];
|
||||
// LeaveCriticalSection (a);
|
||||
// return val;
|
||||
// }
|
||||
double METER::GetMeter (TXA& txa, int mt)
|
||||
{
|
||||
double val;
|
||||
txa.pmtupdate[mt]->lock();
|
||||
val = txa.meter[mt];
|
||||
txa.pmtupdate[mt]->unlock();
|
||||
return val;
|
||||
}
|
||||
|
||||
} // namespace WDSP
|
||||
|
@ -34,6 +34,9 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
class TXA;
|
||||
|
||||
class WDSP_API METER
|
||||
{
|
||||
public:
|
||||
@ -76,19 +79,16 @@ public:
|
||||
static void setBuffers_meter (METER *a, double* in);
|
||||
static void setSamplerate_meter (METER *a, int rate);
|
||||
static void setSize_meter (METER *a, int size);
|
||||
// RXA Properties
|
||||
static double GetMeter (RXA& rxa, int mt);
|
||||
// TXA Properties
|
||||
static double GetMeter (TXA& txa, int mt);
|
||||
|
||||
private:
|
||||
static void calc_meter (METER *a);
|
||||
};
|
||||
|
||||
|
||||
// RXA Properties
|
||||
|
||||
// __declspec (dllexport) double GetRXAMeter (int channel, int mt);
|
||||
|
||||
// TXA Properties
|
||||
|
||||
// __declspec (dllexport) double GetTXAMeter (int channel, int mt);
|
||||
|
||||
} // namespace WDSP
|
||||
|
||||
|
@ -28,20 +28,11 @@ warren@wpratt.com
|
||||
#include "comm.hpp"
|
||||
#include "sender.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "bufferprobe.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
void SENDER::calc_sender (SENDER *a)
|
||||
{
|
||||
a->out = new double[a->size * 2]; // (double *) malloc0 (a->size * sizeof (complex));
|
||||
}
|
||||
|
||||
void decalc_sender (SENDER *a)
|
||||
{
|
||||
delete[] (a->out);
|
||||
}
|
||||
|
||||
SENDER* SENDER::create_sender (int run, int flag, int mode, int size, double* in, int arg0, int arg1, int arg2, int arg3)
|
||||
SENDER* SENDER::create_sender (int run, int flag, int mode, int size, double* in)
|
||||
{
|
||||
SENDER *a = new SENDER;
|
||||
a->run = run;
|
||||
@ -49,23 +40,17 @@ SENDER* SENDER::create_sender (int run, int flag, int mode, int size, double* in
|
||||
a->mode = mode;
|
||||
a->size = size;
|
||||
a->in = in;
|
||||
a->arg0 = arg0;
|
||||
a->arg1 = arg1;
|
||||
a->arg2 = arg2;
|
||||
a->arg3 = arg3;
|
||||
calc_sender (a);
|
||||
a->spectrumProbe = nullptr;
|
||||
return a;
|
||||
}
|
||||
|
||||
void SENDER::destroy_sender (SENDER *a)
|
||||
{
|
||||
decalc_sender (a);
|
||||
delete (a);
|
||||
}
|
||||
|
||||
void SENDER::flush_sender (SENDER *a)
|
||||
void SENDER::flush_sender (SENDER *)
|
||||
{
|
||||
memset (a->out, 0, a->size * sizeof (dcomplex));
|
||||
}
|
||||
|
||||
void SENDER::xsender (SENDER *a)
|
||||
@ -76,14 +61,9 @@ void SENDER::xsender (SENDER *a)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
int i;
|
||||
dINREAL* outf = (dINREAL *)a->out;
|
||||
for (i = 0; i < a->size; i++)
|
||||
{
|
||||
outf [2 * i + 0] = (dINREAL)a->in[2 * i + 0];
|
||||
outf [2 * i + 1] = (dINREAL)a->in[2 * i + 1];
|
||||
if (a->spectrumProbe) {
|
||||
a->spectrumProbe->proceed(a->in, a->size);
|
||||
}
|
||||
// Spectrum2 (1, a->arg0, a->arg1, a->arg2, outf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -102,9 +82,7 @@ void SENDER::setSamplerate_sender (SENDER *a, int)
|
||||
|
||||
void SENDER::setSize_sender (SENDER *a, int size)
|
||||
{
|
||||
decalc_sender (a);
|
||||
a->size = size;
|
||||
calc_sender (a);
|
||||
}
|
||||
|
||||
/********************************************************************************************************
|
||||
@ -113,15 +91,13 @@ void SENDER::setSize_sender (SENDER *a, int size)
|
||||
* *
|
||||
********************************************************************************************************/
|
||||
|
||||
void SENDER::SetSpectrum (RXA& rxa, int flag, int disp, int ss, int LO)
|
||||
void SENDER::SetSpectrum (RXA& rxa, int flag, BufferProbe *spectrumProbe)
|
||||
{
|
||||
SENDER *a;
|
||||
rxa.csDSP.lock();
|
||||
a = rxa.sender.p;
|
||||
a->flag = flag;
|
||||
a->arg0 = disp;
|
||||
a->arg1 = ss;
|
||||
a->arg2 = LO;
|
||||
a->spectrumProbe = spectrumProbe;
|
||||
rxa.csDSP.unlock();
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ warren@wpratt.com
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
class BufferProbe;
|
||||
|
||||
class WDSP_API SENDER
|
||||
{
|
||||
@ -47,14 +48,9 @@ public:
|
||||
int mode; // selects the specific processing and function call
|
||||
int size; // size of the data buffer (complex samples)
|
||||
double* in; // buffer from which to take the data
|
||||
int arg0; // parameters that can be passed to the function called
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
double* out; // internally created buffer into which processed data is placed
|
||||
// a pointer to *out is passed to the external function that is called
|
||||
BufferProbe *spectrumProbe; // this is the data handler actually
|
||||
|
||||
static SENDER* create_sender (int run, int flag, int mode, int size, double* in, int arg0, int arg1, int arg2, int arg3);
|
||||
static SENDER* create_sender (int run, int flag, int mode, int size, double* in);
|
||||
static void destroy_sender (SENDER *a);
|
||||
static void flush_sender (SENDER *a);
|
||||
static void xsender (SENDER *a);
|
||||
@ -62,12 +58,8 @@ public:
|
||||
static void setSamplerate_sender (SENDER *a, int rate);
|
||||
static void setSize_sender (SENDER *a, int size);
|
||||
// RXA Properties
|
||||
static void SetSpectrum (RXA& rxa, int flag, int disp, int ss, int LO);
|
||||
static void SetSpectrum (RXA& rxa, int flag, BufferProbe *spectrumProbe);
|
||||
// TXA Properties
|
||||
|
||||
private:
|
||||
static void calc_sender (SENDER *a);
|
||||
static void decalc_sender (SENDER *a);
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
Loading…
Reference in New Issue
Block a user