mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-25 21:28:38 -05:00
Merge pull request #414 from cjcliffe/fms_deemphasis
FM Stereo de-emphasis
This commit is contained in:
commit
61aa57884f
@ -1003,6 +1003,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
|||||||
waterfallSpeedMeter->Refresh();
|
waterfallSpeedMeter->Refresh();
|
||||||
spectrumAvgMeter->Refresh();
|
spectrumAvgMeter->Refresh();
|
||||||
gainCanvas->setThemeColors();
|
gainCanvas->setThemeColors();
|
||||||
|
modemProps->updateTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event.GetId()) {
|
switch (event.GetId()) {
|
||||||
@ -1498,6 +1499,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
modemProps->initProperties(demod->getModemArgs());
|
modemProps->initProperties(demod->getModemArgs());
|
||||||
modemPropertiesUpdated.store(false);
|
modemPropertiesUpdated.store(false);
|
||||||
demodTray->Layout();
|
demodTray->Layout();
|
||||||
|
modemProps->fitColumns();
|
||||||
#if ENABLE_DIGITAL_LAB
|
#if ENABLE_DIGITAL_LAB
|
||||||
if (demod->getModemType() == "digital") {
|
if (demod->getModemType() == "digital") {
|
||||||
ModemDigitalOutputConsole *outp = (ModemDigitalOutputConsole *)demod->getOutput();
|
ModemDigitalOutputConsole *outp = (ModemDigitalOutputConsole *)demod->getOutput();
|
||||||
@ -1510,6 +1512,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (modemProps->isCollapsed() && modemProps->GetMinWidth() > 22) {
|
||||||
|
modemProps->SetMinSize(wxSize(22,-1));
|
||||||
|
modemProps->SetMaxSize(wxSize(22,-1));
|
||||||
|
demodTray->Layout();
|
||||||
|
modemProps->fitColumns();
|
||||||
|
} else if (!modemProps->isCollapsed() && modemProps->GetMinWidth() < 200) {
|
||||||
|
modemProps->SetMinSize(wxSize(200,-1));
|
||||||
|
modemProps->SetMaxSize(wxSize(200,-1));
|
||||||
|
demodTray->Layout();
|
||||||
|
modemProps->fitColumns();
|
||||||
|
}
|
||||||
|
|
||||||
int peakHoldMode = peakHoldButton->getSelection();
|
int peakHoldMode = peakHoldButton->getSelection();
|
||||||
if (peakHoldButton->modeChanged()) {
|
if (peakHoldButton->modeChanged()) {
|
||||||
wxGetApp().getSpectrumProcessor()->setPeakHold(peakHoldMode == 1);
|
wxGetApp().getSpectrumProcessor()->setPeakHold(peakHoldMode == 1);
|
||||||
|
@ -4,24 +4,62 @@
|
|||||||
ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid,
|
ModemProperties::ModemProperties(wxWindow *parent, wxWindowID winid,
|
||||||
const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) {
|
const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) {
|
||||||
|
|
||||||
m_propertyGrid = new wxPropertyGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE);
|
m_propertyGrid = new wxPropertyGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE | wxPG_NO_INTERNAL_BORDER);
|
||||||
|
|
||||||
bSizer = new wxBoxSizer( wxVERTICAL );
|
bSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
bSizer->Add(m_propertyGrid, 1, wxEXPAND, 5);
|
bSizer->Add(m_propertyGrid, 1, wxEXPAND, 0);
|
||||||
|
|
||||||
this->SetSizer(bSizer);
|
this->SetSizer(bSizer);
|
||||||
|
|
||||||
|
m_propertyGrid->Connect( wxEVT_PG_ITEM_COLLAPSED, wxPropertyGridEventHandler( ModemProperties::OnCollapse ), NULL, this );
|
||||||
|
m_propertyGrid->Connect( wxEVT_PG_ITEM_EXPANDED, wxPropertyGridEventHandler( ModemProperties::OnExpand ), NULL, this );
|
||||||
m_propertyGrid->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( ModemProperties::OnChange ), NULL, this );
|
m_propertyGrid->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( ModemProperties::OnChange ), NULL, this );
|
||||||
this->Connect( wxEVT_SHOW, wxShowEventHandler( ModemProperties::OnShow ), NULL, this );
|
this->Connect( wxEVT_SHOW, wxShowEventHandler( ModemProperties::OnShow ), NULL, this );
|
||||||
|
|
||||||
this->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseEnter ), NULL, this);
|
this->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseEnter ), NULL, this);
|
||||||
this->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseLeave ), NULL, this);
|
this->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( ModemProperties::OnMouseLeave ), NULL, this);
|
||||||
|
|
||||||
|
updateTheme();
|
||||||
|
|
||||||
mouseInView = false;
|
mouseInView = false;
|
||||||
|
collapsed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemProperties::OnShow(wxShowEvent & /* event */) {
|
void ModemProperties::OnShow(wxShowEvent & /* event */) {
|
||||||
|
updateTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::updateTheme() {
|
||||||
|
wxColour bgColor(
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->generalBackground.r * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->generalBackground.g * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->generalBackground.b * 255.0));
|
||||||
|
|
||||||
|
wxColour textColor(
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->text.r * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->text.g * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->text.b * 255.0));
|
||||||
|
|
||||||
|
wxColour btn(
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->button.r * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->button.g * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->button.b * 255.0));
|
||||||
|
|
||||||
|
wxColour btnHl(
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->buttonHighlight.r * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->buttonHighlight.g * 255.0),
|
||||||
|
(unsigned char) (ThemeMgr::mgr.currentTheme->buttonHighlight.b * 255.0));
|
||||||
|
|
||||||
|
|
||||||
|
m_propertyGrid->SetEmptySpaceColour(bgColor);
|
||||||
|
m_propertyGrid->SetCellBackgroundColour(bgColor);
|
||||||
|
m_propertyGrid->SetCellTextColour(textColor);
|
||||||
|
m_propertyGrid->SetSelectionTextColour(bgColor);
|
||||||
|
m_propertyGrid->SetSelectionBackgroundColour(btnHl);
|
||||||
|
m_propertyGrid->SetCaptionTextColour(bgColor);
|
||||||
|
m_propertyGrid->SetCaptionBackgroundColour(btn);
|
||||||
|
m_propertyGrid->SetLineColour(btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModemProperties::~ModemProperties() {
|
ModemProperties::~ModemProperties() {
|
||||||
@ -51,6 +89,10 @@ void ModemProperties::initProperties(ModemArgInfoList newArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_propertyGrid->FitColumns();
|
m_propertyGrid->FitColumns();
|
||||||
|
|
||||||
|
if (collapsed) {
|
||||||
|
m_propertyGrid->CollapseAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxPGProperty *ModemProperties::addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg) {
|
wxPGProperty *ModemProperties::addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg) {
|
||||||
@ -166,6 +208,14 @@ void ModemProperties::OnChange(wxPropertyGridEvent &event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModemProperties::OnCollapse(wxPropertyGridEvent &event) {
|
||||||
|
collapsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::OnExpand(wxPropertyGridEvent &event) {
|
||||||
|
collapsed = false;
|
||||||
|
}
|
||||||
|
|
||||||
void ModemProperties::OnMouseEnter(wxMouseEvent & /* event */) {
|
void ModemProperties::OnMouseEnter(wxMouseEvent & /* event */) {
|
||||||
mouseInView = true;
|
mouseInView = true;
|
||||||
}
|
}
|
||||||
@ -177,3 +227,11 @@ void ModemProperties::OnMouseLeave(wxMouseEvent & /* event */) {
|
|||||||
bool ModemProperties::isMouseInView() {
|
bool ModemProperties::isMouseInView() {
|
||||||
return mouseInView || (m_propertyGrid && m_propertyGrid->IsEditorFocused());
|
return mouseInView || (m_propertyGrid && m_propertyGrid->IsEditorFocused());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ModemProperties::isCollapsed() {
|
||||||
|
return collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemProperties::fitColumns() {
|
||||||
|
m_propertyGrid->FitColumns();
|
||||||
|
}
|
||||||
|
@ -21,12 +21,18 @@ public:
|
|||||||
|
|
||||||
void initProperties(ModemArgInfoList newArgs);
|
void initProperties(ModemArgInfoList newArgs);
|
||||||
bool isMouseInView();
|
bool isMouseInView();
|
||||||
|
bool isCollapsed();
|
||||||
|
void fitColumns();
|
||||||
|
|
||||||
|
void updateTheme();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg);
|
wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, ModemArgInfo arg);
|
||||||
std::string readProperty(std::string);
|
std::string readProperty(std::string);
|
||||||
void OnChange(wxPropertyGridEvent &event);
|
void OnChange(wxPropertyGridEvent &event);
|
||||||
void OnShow(wxShowEvent &event);
|
void OnShow(wxShowEvent &event);
|
||||||
|
void OnCollapse(wxPropertyGridEvent &event);
|
||||||
|
void OnExpand(wxPropertyGridEvent &event);
|
||||||
|
|
||||||
void OnMouseEnter(wxMouseEvent &event);
|
void OnMouseEnter(wxMouseEvent &event);
|
||||||
void OnMouseLeave(wxMouseEvent &event);
|
void OnMouseLeave(wxMouseEvent &event);
|
||||||
@ -35,5 +41,5 @@ private:
|
|||||||
wxPropertyGrid* m_propertyGrid;
|
wxPropertyGrid* m_propertyGrid;
|
||||||
ModemArgInfoList args;
|
ModemArgInfoList args;
|
||||||
std::map<std::string, wxPGProperty *> props;
|
std::map<std::string, wxPGProperty *> props;
|
||||||
bool mouseInView;
|
bool mouseInView, collapsed;
|
||||||
};
|
};
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
ModemFMStereo::ModemFMStereo() {
|
ModemFMStereo::ModemFMStereo() {
|
||||||
demodFM = freqdem_create(0.5);
|
demodFM = freqdem_create(0.5);
|
||||||
|
_demph = 75;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModemFMStereo::~ModemFMStereo() {
|
ModemFMStereo::~ModemFMStereo() {
|
||||||
@ -34,6 +35,54 @@ int ModemFMStereo::getDefaultSampleRate() {
|
|||||||
return 200000;
|
return 200000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModemArgInfoList ModemFMStereo::getSettings() {
|
||||||
|
ModemArgInfoList args;
|
||||||
|
|
||||||
|
ModemArgInfo demphArg;
|
||||||
|
demphArg.key = "demph";
|
||||||
|
demphArg.name = "De-emphasis";
|
||||||
|
demphArg.value = std::to_string(_demph);
|
||||||
|
demphArg.description = "FM Stereo De-Emphasis, typically 75us in US/Canada, 50us elsewhere.";
|
||||||
|
|
||||||
|
demphArg.type = ModemArgInfo::STRING;
|
||||||
|
|
||||||
|
std::vector<std::string> demphOptNames;
|
||||||
|
demphOptNames.push_back("None");
|
||||||
|
demphOptNames.push_back("10us");
|
||||||
|
demphOptNames.push_back("25us");
|
||||||
|
demphOptNames.push_back("32us");
|
||||||
|
demphOptNames.push_back("50us");
|
||||||
|
demphOptNames.push_back("75us");
|
||||||
|
demphArg.optionNames = demphOptNames;
|
||||||
|
|
||||||
|
std::vector<std::string> demphOpts;
|
||||||
|
demphOpts.push_back("0");
|
||||||
|
demphOpts.push_back("10");
|
||||||
|
demphOpts.push_back("25");
|
||||||
|
demphOpts.push_back("32");
|
||||||
|
demphOpts.push_back("50");
|
||||||
|
demphOpts.push_back("75");
|
||||||
|
demphArg.options = demphOpts;
|
||||||
|
|
||||||
|
args.push_back(demphArg);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemFMStereo::writeSetting(std::string setting, std::string value) {
|
||||||
|
if (setting == "demph") {
|
||||||
|
_demph = std::stoi(value);
|
||||||
|
rebuildKit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModemFMStereo::readSetting(std::string setting) {
|
||||||
|
if (setting == "demph") {
|
||||||
|
return std::to_string(_demph);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
|
ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
ModemKitFMStereo *kit = new ModemKitFMStereo;
|
ModemKitFMStereo *kit = new ModemKitFMStereo;
|
||||||
|
|
||||||
@ -87,6 +136,24 @@ ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
|
|||||||
nco_crcf_reset(kit->stereoPilot);
|
nco_crcf_reset(kit->stereoPilot);
|
||||||
nco_crcf_pll_set_bandwidth(kit->stereoPilot, 0.25f);
|
nco_crcf_pll_set_bandwidth(kit->stereoPilot, 0.25f);
|
||||||
|
|
||||||
|
kit->demph = _demph;
|
||||||
|
|
||||||
|
if (_demph) {
|
||||||
|
float f = (1.0f / (2.0f * M_PI * double(_demph) * 1e-6));
|
||||||
|
float t = 1.0f / (2.0f * M_PI * f);
|
||||||
|
t = 1.0f / (2.0f * float(audioSampleRate) * tan(1.0f / (2.0f * float(audioSampleRate) * t)));
|
||||||
|
|
||||||
|
float tb = (1.0f + 2.0f * t * float(audioSampleRate));
|
||||||
|
float b_demph[2] = { 1.0f / tb, 1.0f / tb };
|
||||||
|
float a_demph[2] = { 1.0f, (1.0f - 2.0f * t * float(audioSampleRate)) / tb };
|
||||||
|
|
||||||
|
kit->iirDemphL = iirfilt_rrrf_create(b_demph, 2, a_demph, 2);
|
||||||
|
kit->iirDemphR = iirfilt_rrrf_create(b_demph, 2, a_demph, 2);
|
||||||
|
} else {
|
||||||
|
kit->iirDemphL = nullptr;
|
||||||
|
kit->iirDemphR = nullptr;
|
||||||
|
kit->demph = 0;
|
||||||
|
}
|
||||||
return kit;
|
return kit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +167,8 @@ void ModemFMStereo::disposeKit(ModemKit *kit) {
|
|||||||
firhilbf_destroy(fmkit->firStereoR2C);
|
firhilbf_destroy(fmkit->firStereoR2C);
|
||||||
firhilbf_destroy(fmkit->firStereoC2R);
|
firhilbf_destroy(fmkit->firStereoC2R);
|
||||||
nco_crcf_destroy(fmkit->stereoPilot);
|
nco_crcf_destroy(fmkit->stereoPilot);
|
||||||
|
if (fmkit->iirDemphR) { iirfilt_rrrf_destroy(fmkit->iirDemphR); }
|
||||||
|
if (fmkit->iirDemphL) { iirfilt_rrrf_destroy(fmkit->iirDemphL); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -189,12 +258,24 @@ void ModemFMStereo::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInp
|
|||||||
audioOut->data.resize(numAudioWritten * 2);
|
audioOut->data.resize(numAudioWritten * 2);
|
||||||
for (size_t i = 0; i < numAudioWritten; i++) {
|
for (size_t i = 0; i < numAudioWritten; i++) {
|
||||||
float l, r;
|
float l, r;
|
||||||
|
float ld, rd;
|
||||||
|
|
||||||
|
if (fmkit->demph) {
|
||||||
|
iirfilt_rrrf_execute(fmkit->iirDemphL, 0.568f * (resampledOutputData[i] - (resampledStereoData[i])), &ld);
|
||||||
|
iirfilt_rrrf_execute(fmkit->iirDemphR, 0.568f * (resampledOutputData[i] + (resampledStereoData[i])), &rd);
|
||||||
|
|
||||||
|
firfilt_rrrf_push(fmkit->firStereoLeft, ld);
|
||||||
|
firfilt_rrrf_execute(fmkit->firStereoLeft, &l);
|
||||||
|
|
||||||
|
firfilt_rrrf_push(fmkit->firStereoRight, rd);
|
||||||
|
firfilt_rrrf_execute(fmkit->firStereoRight, &r);
|
||||||
|
} else {
|
||||||
firfilt_rrrf_push(fmkit->firStereoLeft, 0.568f * (resampledOutputData[i] - (resampledStereoData[i])));
|
firfilt_rrrf_push(fmkit->firStereoLeft, 0.568f * (resampledOutputData[i] - (resampledStereoData[i])));
|
||||||
firfilt_rrrf_execute(fmkit->firStereoLeft, &l);
|
firfilt_rrrf_execute(fmkit->firStereoLeft, &l);
|
||||||
|
|
||||||
firfilt_rrrf_push(fmkit->firStereoRight, 0.568f * (resampledOutputData[i] + (resampledStereoData[i])));
|
firfilt_rrrf_push(fmkit->firStereoRight, 0.568f * (resampledOutputData[i] + (resampledStereoData[i])));
|
||||||
firfilt_rrrf_execute(fmkit->firStereoRight, &r);
|
firfilt_rrrf_execute(fmkit->firStereoRight, &r);
|
||||||
|
}
|
||||||
|
|
||||||
audioOut->data[i * 2] = l;
|
audioOut->data[i * 2] = l;
|
||||||
audioOut->data[i * 2 + 1] = r;
|
audioOut->data[i * 2 + 1] = r;
|
||||||
|
@ -14,6 +14,10 @@ public:
|
|||||||
firfilt_rrrf firStereoRight;
|
firfilt_rrrf firStereoRight;
|
||||||
iirfilt_crcf iirStereoPilot;
|
iirfilt_crcf iirStereoPilot;
|
||||||
|
|
||||||
|
int demph;
|
||||||
|
iirfilt_rrrf iirDemphR;
|
||||||
|
iirfilt_rrrf iirDemphL;
|
||||||
|
|
||||||
firhilbf firStereoR2C;
|
firhilbf firStereoR2C;
|
||||||
firhilbf firStereoC2R;
|
firhilbf firStereoC2R;
|
||||||
|
|
||||||
@ -34,6 +38,10 @@ public:
|
|||||||
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
int checkSampleRate(long long sampleRate, int audioSampleRate);
|
||||||
int getDefaultSampleRate();
|
int getDefaultSampleRate();
|
||||||
|
|
||||||
|
ModemArgInfoList getSettings();
|
||||||
|
void writeSetting(std::string setting, std::string value);
|
||||||
|
std::string readSetting(std::string setting);
|
||||||
|
|
||||||
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
void disposeKit(ModemKit *kit);
|
void disposeKit(ModemKit *kit);
|
||||||
|
|
||||||
@ -45,4 +53,6 @@ private:
|
|||||||
std::vector<float> resampledOutputData;
|
std::vector<float> resampledOutputData;
|
||||||
std::vector<float> resampledStereoData;
|
std::vector<float> resampledStereoData;
|
||||||
freqdem demodFM;
|
freqdem demodFM;
|
||||||
|
|
||||||
|
int _demph;
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user