Add optional legacy JMBE tone levels to digital channel editors (#2511)

Persist the per-channel selection, preserve it when copying configurations, and transfer it to mixed-phase P25 traffic channels. Apply only when the loaded codec advertises support. Calibrated levels remain the default.
This commit is contained in:
GTR8000
2026-10-30 03:43:36 -04:00
committed by GitHub
parent 248fe3e4f7
commit d86fba6945
6 changed files with 117 additions and 0 deletions

View File

@@ -94,6 +94,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
private Spinner<Integer> mChannelRotationDelaySpinner;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private ToggleSwitch mLegacyToneLevelsButton;
private Slider mJmbeNoiseGainSlider;
/**
@@ -226,6 +227,9 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
row++;
gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1);
mDecoderPane.setContent(gridPane);
}
@@ -589,6 +593,21 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
return mJmbeAGCButton;
}
private ToggleSwitch getLegacyToneLevelsButton()
{
if(mLegacyToneLevelsButton == null)
{
mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels");
mLegacyToneLevelsButton.setTooltip(new Tooltip(
"Restore JMBE 1.x AMBE tone levels. Requires a supporting JMBE library; " +
"stock libraries ignore this option. Tone Volume still adjusts the selected level."));
mLegacyToneLevelsButton.setDisable(true);
mLegacyToneLevelsButton.selectedProperty().addListener(
(o, oldValue, newValue) -> modifiedProperty().set(true));
}
return mLegacyToneLevelsButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
@@ -678,6 +697,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setDisable(disable);
getJmbeNoiseGainSlider().setDisable(disable);
getJmbeToneGainSlider().setDisable(disable);
getLegacyToneLevelsButton().setDisable(disable);
if(config instanceof DecodeConfigDMR)
{
@@ -696,6 +716,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setSelected(decodeConfig.isAGC());
getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain());
getJmbeToneGainSlider().setValue(decodeConfig.getToneGain());
getLegacyToneLevelsButton().setSelected(decodeConfig.isLegacyToneLevels());
}
else
{
@@ -707,6 +728,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
getLegacyToneLevelsButton().setSelected(false);
}
}
@@ -732,6 +754,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected());
getItem().setDecodeConfiguration(config);
}

View File

@@ -97,6 +97,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
private ToggleSwitch mIgnoreEncryptedCallsToggle;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private ToggleSwitch mLegacyToneLevelsButton;
private Slider mJmbeNoiseGainSlider;
/**
@@ -232,6 +233,9 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
row++;
gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1);
mDecoderPane.setContent(gridPane);
}
@@ -569,6 +573,21 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
return mJmbeAGCButton;
}
private ToggleSwitch getLegacyToneLevelsButton()
{
if(mLegacyToneLevelsButton == null)
{
mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels");
mLegacyToneLevelsButton.setTooltip(new Tooltip(
"Restore JMBE 1.x AMBE tone levels. Requires a supporting JMBE library; " +
"stock libraries ignore this option. Tone Volume still adjusts the selected level."));
mLegacyToneLevelsButton.setDisable(true);
mLegacyToneLevelsButton.selectedProperty().addListener(
(o, oldValue, newValue) -> modifiedProperty().set(true));
}
return mLegacyToneLevelsButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
@@ -658,6 +677,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setDisable(disable);
getJmbeNoiseGainSlider().setDisable(disable);
getJmbeToneGainSlider().setDisable(disable);
getLegacyToneLevelsButton().setDisable(disable);
if(config instanceof DecodeConfigNXDN configNXDN)
{
@@ -681,6 +701,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setSelected(configNXDN.isAGC());
getJmbeNoiseGainSlider().setValue(configNXDN.getNoiseGain());
getJmbeToneGainSlider().setValue(configNXDN.getToneGain());
getLegacyToneLevelsButton().setSelected(configNXDN.isLegacyToneLevels());
}
else
{
@@ -691,6 +712,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
getLegacyToneLevelsButton().setSelected(false);
}
}
@@ -726,6 +748,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected());
getItem().setDecodeConfiguration(config);
}

View File

@@ -78,6 +78,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
private ToggleButton mLSMToggleButton;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private ToggleSwitch mLegacyToneLevelsButton;
private Slider mJmbeNoiseGainSlider;
/**
@@ -177,6 +178,9 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS);
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
row++;
gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1);
mDecoderPane.setContent(gridPane);
}
@@ -291,6 +295,21 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
return mJmbeAGCButton;
}
private ToggleSwitch getLegacyToneLevelsButton()
{
if(mLegacyToneLevelsButton == null)
{
mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels");
mLegacyToneLevelsButton.setTooltip(new Tooltip(
"Restore JMBE 1.x AMBE tone levels. Requires a supporting JMBE library; " +
"stock libraries ignore this option. Tone Volume still adjusts the selected level."));
mLegacyToneLevelsButton.setDisable(true);
mLegacyToneLevelsButton.selectedProperty().addListener(
(o, oldValue, newValue) -> modifiedProperty().set(true));
}
return mLegacyToneLevelsButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
@@ -411,9 +430,11 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setDisable(false);
getJmbeNoiseGainSlider().setDisable(false);
getJmbeToneGainSlider().setDisable(false);
getLegacyToneLevelsButton().setDisable(false);
getJmbeAGCButton().setSelected(decodeConfig.isAGC());
getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain());
getJmbeToneGainSlider().setValue(decodeConfig.getToneGain());
getLegacyToneLevelsButton().setSelected(decodeConfig.isLegacyToneLevels());
}
else
@@ -423,9 +444,11 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setDisable(true);
getJmbeNoiseGainSlider().setDisable(true);
getJmbeToneGainSlider().setDisable(true);
getLegacyToneLevelsButton().setDisable(true);
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
getLegacyToneLevelsButton().setSelected(false);
}
}
@@ -449,6 +472,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected());
getItem().setDecodeConfiguration(config);
}

View File

@@ -74,6 +74,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
private Spinner<Integer> mTrafficChannelPoolSizeSpinner;
private ToggleSwitch mJmbeAGCButton;
private Slider mJmbeToneGainSlider;
private ToggleSwitch mLegacyToneLevelsButton;
private Slider mJmbeNoiseGainSlider;
/**
@@ -188,6 +189,9 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
gridPane.add(getJmbeNoiseGainSlider(), 5, row);
row++;
gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1);
mDecoderPane.setContent(gridPane);
}
@@ -207,6 +211,21 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
return mJmbeAGCButton;
}
private ToggleSwitch getLegacyToneLevelsButton()
{
if(mLegacyToneLevelsButton == null)
{
mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels");
mLegacyToneLevelsButton.setTooltip(new Tooltip(
"Restore JMBE 1.x AMBE tone levels. Requires a supporting JMBE library; " +
"stock libraries ignore this option. Tone Volume still adjusts the selected level."));
mLegacyToneLevelsButton.setDisable(true);
mLegacyToneLevelsButton.selectedProperty().addListener(
(o, oldValue, newValue) -> modifiedProperty().set(true));
}
return mLegacyToneLevelsButton;
}
public Slider getJmbeToneGainSlider()
{
if(mJmbeToneGainSlider == null)
@@ -392,6 +411,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setDisable(false);
getJmbeNoiseGainSlider().setDisable(false);
getJmbeToneGainSlider().setDisable(false);
getLegacyToneLevelsButton().setDisable(false);
ScrambleParameters scrambleParameters = decodeConfig.getScrambleParameters();
@@ -415,6 +435,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setSelected(decodeConfig.isAGC());
getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain());
getJmbeToneGainSlider().setValue(decodeConfig.getToneGain());
getLegacyToneLevelsButton().setSelected(decodeConfig.isLegacyToneLevels());
}
else
{
@@ -429,9 +450,11 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
getJmbeAGCButton().setDisable(true);
getJmbeNoiseGainSlider().setDisable(true);
getJmbeToneGainSlider().setDisable(true);
getLegacyToneLevelsButton().setDisable(true);
getJmbeAGCButton().setSelected(false);
getJmbeNoiseGainSlider().setValue(0);
getJmbeToneGainSlider().setValue(0);
getLegacyToneLevelsButton().setSelected(false);
}
}
@@ -459,6 +482,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
config.setAGC(getJmbeAGCButton().selectedProperty().getValue());
config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue());
config.setToneGain((float)getJmbeToneGainSlider().getValue());
config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected());
getItem().setDecodeConfiguration(config);
}

View File

@@ -571,6 +571,12 @@ public class DecoderFactory
{
List<String> features = audioModule.getFeatures();
String legacyToneFeature = "feature_legacy_tone_levels";
if(features.contains(legacyToneFeature))
{
audioModule.setFeature(legacyToneFeature, config.isLegacyToneLevels());
}
if(features.contains(IAudioCodecV2.FEATURE_AUTOMATIC_GAIN_CONTROL))
{
audioModule.setFeature(IAudioCodecV2.FEATURE_AUTOMATIC_GAIN_CONTROL, config.isAGC());
@@ -952,5 +958,6 @@ public class DecoderFactory
to.setAGC(from.isAGC());
to.setNoiseGain(from.getNoiseGain());
to.setToneGain(from.getToneGain());
to.setLegacyToneLevels(from.isLegacyToneLevels());
}
}

View File

@@ -5,6 +5,22 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
public abstract class DecodeConfigJMBE extends DecodeConfiguration
{
private boolean mAGC = true;
private boolean mLegacyToneLevels;
/**
* Optional legacy AMBE tone amplitude mapping. Disabled by default.
* Requires a JMBE library supporting feature_legacy_tone_levels.
*/
@JacksonXmlProperty(isAttribute = true, localName = "jmbeLegacyToneLevels", namespace = "http://www.w3.org/2001/XMLSchema-instance")
public boolean isLegacyToneLevels()
{
return mLegacyToneLevels;
}
public void setLegacyToneLevels(boolean enabled)
{
mLegacyToneLevels = enabled;
}
private float mToneGain = 1.0f;
private float mNoiseGain = 1.0f;