diff --git a/build.gradle b/build.gradle index 1456ee5f..33b3045d 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ dependencies { //Jitpack imports implementation 'com.github.dnault:libresample4j:master' - implementation 'com.github.DSheirer.jmbe:api:v2.0.0' + implementation 'com.github.DSheirer.jmbe:api:v2.1.0' implementation 'com.github.nwaldispuehl:java-lame:v3.98.4' //mavenCentral/jcenter imports diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/ChannelConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/ChannelConfigurationEditor.java index 67966d90..f37ffa91 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/ChannelConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/ChannelConfigurationEditor.java @@ -29,6 +29,7 @@ import io.github.dsheirer.gui.preference.PreferenceEditorType; import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest; import io.github.dsheirer.module.decode.DecoderType; import io.github.dsheirer.module.decode.config.AuxDecodeConfiguration; +import io.github.dsheirer.module.decode.config.DecodeConfigJMBE; import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.log.config.EventLogConfiguration; import io.github.dsheirer.playlist.PlaylistManager; @@ -41,6 +42,7 @@ import io.github.dsheirer.util.ThreadPool; import java.util.Optional; import java.util.function.Predicate; import javafx.application.Platform; +import javafx.beans.binding.Bindings; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.transformation.FilteredList; @@ -48,6 +50,7 @@ import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.HPos; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.ButtonType; @@ -55,14 +58,18 @@ import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; +import javafx.scene.control.Slider; import javafx.scene.control.Spinner; import javafx.scene.control.SpinnerValueFactory; import javafx.scene.control.TextField; import javafx.scene.control.TextFormatter; import javafx.scene.control.TextInputDialog; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import jiconfont.icons.font_awesome.FontAwesome; @@ -681,6 +688,83 @@ public abstract class ChannelConfigurationEditor extends Editor return mNewAliasListButton; } + /** + * Adds the JMBE audio controls to the decoder grid as a nested grid so that they don't have to align with the + * columns of the decoder rows above them, and keeps column 3 of the decoder grid as the growing column. + * @param gridPane decoder grid + * @param row in the decoder grid + * @param title label for the audio controls + * @param noiseGainSlider for comfort noise insertion gain + * @param agcSwitch for automatic gain control + * @param toneGainSlider for tone generation gain + * @param legacyToneLevelsSwitch for legacy tone levels + */ + protected void addAudioControls(GridPane gridPane, int row, String title, Slider noiseGainSlider, + ToggleSwitch agcSwitch, Slider toneGainSlider, ToggleSwitch legacyToneLevelsSwitch) + { + GridPane audioPane = new GridPane(); + audioPane.setHgap(10); + audioPane.setVgap(10); + + audioPane.add(new Label(title), 0, 0); + Label noiseGainLabel = new Label("Comfort Noise Volume:"); + GridPane.setHalignment(noiseGainLabel, HPos.RIGHT); + audioPane.add(noiseGainLabel, 1, 0); + audioPane.add(createSliderWithReset(noiseGainSlider, DecodeConfigJMBE.DEFAULT_COMFORT_NOISE_GAIN), 2, 0); + Label agcLabel = new Label("AGC:"); + agcLabel.setTooltip(agcSwitch.getTooltip()); + GridPane.setHalignment(agcLabel, HPos.RIGHT); + audioPane.add(agcLabel, 3, 0); + audioPane.add(agcSwitch, 4, 0); + + Label toneGainLabel = new Label("Tone Volume:"); + GridPane.setHalignment(toneGainLabel, HPos.RIGHT); + audioPane.add(toneGainLabel, 1, 1); + audioPane.add(createSliderWithReset(toneGainSlider, DecodeConfigJMBE.DEFAULT_TONE_GAIN), 2, 1); + Label legacyToneLevelsLabel = new Label("Use Legacy Tone Levels:"); + legacyToneLevelsLabel.setTooltip(legacyToneLevelsSwitch.getTooltip()); + GridPane.setHalignment(legacyToneLevelsLabel, HPos.RIGHT); + audioPane.add(legacyToneLevelsLabel, 3, 1); + audioPane.add(legacyToneLevelsSwitch, 4, 1); + + ColumnConstraints growColumn = new ColumnConstraints(); + growColumn.setHgrow(Priority.ALWAYS); + gridPane.getColumnConstraints().addAll(new ColumnConstraints(), new ColumnConstraints(), new ColumnConstraints(), + growColumn); + gridPane.add(audioPane, 0, row, 6, 1); + } + + /** + * Creates a horizontally growing box containing the slider and, to the right of the slider, a label showing the + * current slider value and a small reset button. The label and button track the disabled state of the slider. + * @param slider to wrap + * @param defaultValue to apply to the slider when the reset button is clicked + * @return box containing the slider, the value label and the reset button + */ + private HBox createSliderWithReset(Slider slider, double defaultValue) + { + IconNode resetIcon = new IconNode(FontAwesome.UNDO); + resetIcon.setIconSize(10); + + Button resetButton = new Button(); + resetIcon.fillProperty().bind(resetButton.textFillProperty()); + resetButton.setGraphic(resetIcon); + resetButton.setTooltip(new Tooltip("Reset to default value")); + resetButton.disableProperty().bind(slider.disableProperty()); + resetButton.setOnAction(event -> slider.setValue(defaultValue)); + + Label valueLabel = new Label(); + valueLabel.textProperty().bind(Bindings.format("%.2f", slider.valueProperty())); + valueLabel.disableProperty().bind(slider.disableProperty()); + valueLabel.setMinWidth(Region.USE_PREF_SIZE); + + HBox box = new HBox(5, slider, valueLabel, resetButton); + box.setAlignment(Pos.CENTER_LEFT); + HBox.setHgrow(slider, Priority.ALWAYS); + GridPane.setHgrow(box, Priority.ALWAYS); + return box; + } + private VBox getButtonBox() { if(mButtonBox == null) diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java index a2053b12..94ba3634 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/DMRConfigurationEditor.java @@ -40,8 +40,6 @@ import io.github.dsheirer.source.config.SourceConfiguration; import io.github.dsheirer.source.tuner.manager.TunerManager; import java.util.ArrayList; import java.util.List; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; @@ -62,9 +60,7 @@ import javafx.scene.control.Tooltip; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; -import javafx.util.Callback; import org.controlsfx.control.ToggleSwitch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -210,25 +206,8 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor gridPane.getChildren().add(editorBox); row++; - Label jmbeLabel = new Label("AMBE Audio"); - GridPane.setHalignment(jmbeLabel, HPos.LEFT); - gridPane.add(jmbeLabel, 0, row); - - GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT); - gridPane.add(getJmbeAGCButton(), 1, row); - - gridPane.add(new Label("Tone Volume:"), 2, row); - - GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeToneGainSlider(), 3, row); - - gridPane.add(new Label("Comfort Noise Volume:"), 4, row); - - GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeNoiseGainSlider(), 5, row); - - row++; - gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1); + addAudioControls(gridPane, row, "AMBE Audio", getJmbeNoiseGainSlider(), getJmbeAGCButton(), + getJmbeToneGainSlider(), getLegacyToneLevelsButton()); mDecoderPane.setContent(gridPane); } @@ -584,7 +563,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor { if(mJmbeAGCButton == null) { - mJmbeAGCButton = new ToggleSwitch("AGC:"); + mJmbeAGCButton = new ToggleSwitch(); mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume")); mJmbeAGCButton.setDisable(true); mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true)); @@ -597,7 +576,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor { if(mLegacyToneLevelsButton == null) { - mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels"); + mLegacyToneLevelsButton = new ToggleSwitch(); 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.")); @@ -714,7 +693,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor } getJmbeAGCButton().setSelected(decodeConfig.isAGC()); - getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain()); + getJmbeNoiseGainSlider().setValue(decodeConfig.getComfortNoiseGain()); getJmbeToneGainSlider().setValue(decodeConfig.getToneGain()); getLegacyToneLevelsButton().setSelected(decodeConfig.isLegacyToneLevels()); } @@ -752,7 +731,7 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor config.setUseCompressedTalkgroups(getUseCompressedTalkgroupsToggle().isSelected()); config.setTimeslotMap(new ArrayList<>(getTimeslotTable().getItems())); config.setAGC(getJmbeAGCButton().selectedProperty().getValue()); - config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue()); + config.setComfortNoiseGain((float)getJmbeNoiseGainSlider().getValue()); config.setToneGain((float)getJmbeToneGainSlider().getValue()); config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected()); getItem().setDecodeConfiguration(config); diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java index 7c254b31..e455f906 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/NXDNConfigurationEditor.java @@ -64,7 +64,6 @@ import javafx.scene.control.ToggleButton; import javafx.scene.control.Tooltip; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import org.controlsfx.control.SegmentedButton; import org.controlsfx.control.ToggleSwitch; @@ -97,7 +96,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor private ToggleSwitch mIgnoreEncryptedCallsToggle; private ToggleSwitch mJmbeAGCButton; private Slider mJmbeToneGainSlider; - private ToggleSwitch mLegacyToneLevelsButton; + private ToggleSwitch mJmbeLegacyToneLevelsButton; private Slider mJmbeNoiseGainSlider; /** @@ -216,25 +215,8 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor gridPane.getChildren().add(editorBox); row++; - Label jmbeLabel = new Label("AMBE Audio"); - GridPane.setHalignment(jmbeLabel, HPos.LEFT); - gridPane.add(jmbeLabel, 0, row); - - GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT); - gridPane.add(getJmbeAGCButton(), 1, row); - - gridPane.add(new Label("Tone Volume:"), 2, row); - - GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeToneGainSlider(), 3, row); - - gridPane.add(new Label("Comfort Noise Volume:"), 4, row); - - GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeNoiseGainSlider(), 5, row); - - row++; - gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1); + addAudioControls(gridPane, row, "AMBE Audio", getJmbeNoiseGainSlider(), getJmbeAGCButton(), + getJmbeToneGainSlider(), getJmbeLegacyToneLevelsButton()); mDecoderPane.setContent(gridPane); } @@ -564,7 +546,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor { if(mJmbeAGCButton == null) { - mJmbeAGCButton = new ToggleSwitch("AGC:"); + mJmbeAGCButton = new ToggleSwitch(); mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume")); mJmbeAGCButton.setDisable(true); mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true)); @@ -573,19 +555,19 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor return mJmbeAGCButton; } - private ToggleSwitch getLegacyToneLevelsButton() + private ToggleSwitch getJmbeLegacyToneLevelsButton() { - if(mLegacyToneLevelsButton == null) + if(mJmbeLegacyToneLevelsButton == null) { - mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels"); - mLegacyToneLevelsButton.setTooltip(new Tooltip( + mJmbeLegacyToneLevelsButton = new ToggleSwitch(); + mJmbeLegacyToneLevelsButton.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( + mJmbeLegacyToneLevelsButton.setDisable(true); + mJmbeLegacyToneLevelsButton.selectedProperty().addListener( (o, oldValue, newValue) -> modifiedProperty().set(true)); } - return mLegacyToneLevelsButton; + return mJmbeLegacyToneLevelsButton; } public Slider getJmbeToneGainSlider() @@ -677,7 +659,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor getJmbeAGCButton().setDisable(disable); getJmbeNoiseGainSlider().setDisable(disable); getJmbeToneGainSlider().setDisable(disable); - getLegacyToneLevelsButton().setDisable(disable); + getJmbeLegacyToneLevelsButton().setDisable(disable); if(config instanceof DecodeConfigNXDN configNXDN) { @@ -699,9 +681,9 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor getIgnoreDataCallsToggle().setSelected(configNXDN.isIgnoreDataCalls()); getIgnoreEncryptedCallsToggle().setSelected(configNXDN.isIgnoreEncryptedCalls()); getJmbeAGCButton().setSelected(configNXDN.isAGC()); - getJmbeNoiseGainSlider().setValue(configNXDN.getNoiseGain()); + getJmbeNoiseGainSlider().setValue(configNXDN.getComfortNoiseGain()); getJmbeToneGainSlider().setValue(configNXDN.getToneGain()); - getLegacyToneLevelsButton().setSelected(configNXDN.isLegacyToneLevels()); + getJmbeLegacyToneLevelsButton().setSelected(configNXDN.isLegacyToneLevels()); } else { @@ -712,7 +694,7 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor getJmbeAGCButton().setSelected(false); getJmbeNoiseGainSlider().setValue(0); getJmbeToneGainSlider().setValue(0); - getLegacyToneLevelsButton().setSelected(false); + getJmbeLegacyToneLevelsButton().setSelected(false); } } @@ -746,9 +728,9 @@ public class NXDNConfigurationEditor extends ChannelConfigurationEditor config.setIgnoreDataCalls(getIgnoreDataCallsToggle().isSelected()); config.setIgnoreEncryptedCalls(getIgnoreEncryptedCallsToggle().isSelected()); config.setAGC(getJmbeAGCButton().selectedProperty().getValue()); - config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue()); + config.setComfortNoiseGain((float)getJmbeNoiseGainSlider().getValue()); config.setToneGain((float)getJmbeToneGainSlider().getValue()); - config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected()); + config.setLegacyToneLevels(getJmbeLegacyToneLevelsButton().isSelected()); getItem().setDecodeConfiguration(config); } diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java index d1dfe502..c82ac9be 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java @@ -51,7 +51,6 @@ import javafx.scene.control.Toggle; import javafx.scene.control.ToggleButton; import javafx.scene.control.Tooltip; import javafx.scene.layout.GridPane; -import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import org.controlsfx.control.SegmentedButton; import org.controlsfx.control.ToggleSwitch; @@ -161,25 +160,8 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor row++; - Label jmbeLabel = new Label("AMBE/IMBE Audio"); - GridPane.setHalignment(jmbeLabel, HPos.LEFT); - gridPane.add(jmbeLabel, 0, row); - - GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT); - gridPane.add(getJmbeAGCButton(), 1, row); - - gridPane.add(new Label("Tone Volume:"), 2, row); - - GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeToneGainSlider(), 3, row); - - gridPane.add(new Label("Comfort Noise Volume:"), 4, row); - - GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeNoiseGainSlider(), 5, row); - - row++; - gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1); + addAudioControls(gridPane, row, "AMBE/IMBE Audio", getJmbeNoiseGainSlider(), getJmbeAGCButton(), + getJmbeToneGainSlider(), getLegacyToneLevelsButton()); mDecoderPane.setContent(gridPane); } @@ -286,7 +268,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor { if(mJmbeAGCButton == null) { - mJmbeAGCButton = new ToggleSwitch("AGC:"); + mJmbeAGCButton = new ToggleSwitch(); mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume")); mJmbeAGCButton.setDisable(true); mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true)); @@ -299,7 +281,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor { if(mLegacyToneLevelsButton == null) { - mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels"); + mLegacyToneLevelsButton = new ToggleSwitch(); 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.")); @@ -432,7 +414,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor getJmbeToneGainSlider().setDisable(false); getLegacyToneLevelsButton().setDisable(false); getJmbeAGCButton().setSelected(decodeConfig.isAGC()); - getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain()); + getJmbeNoiseGainSlider().setValue(decodeConfig.getComfortNoiseGain()); getJmbeToneGainSlider().setValue(decodeConfig.getToneGain()); getLegacyToneLevelsButton().setSelected(decodeConfig.isLegacyToneLevels()); @@ -470,7 +452,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor config.setTrafficChannelPoolSize(getTrafficChannelPoolSizeSpinner().getValue()); config.setModulation(getC4FMToggleButton().isSelected() ? Modulation.C4FM : Modulation.CQPSK); config.setAGC(getJmbeAGCButton().selectedProperty().getValue()); - config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue()); + config.setComfortNoiseGain((float)getJmbeNoiseGainSlider().getValue()); config.setToneGain((float)getJmbeToneGainSlider().getValue()); config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected()); getItem().setDecodeConfiguration(config); diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java index a65c41c7..f0161a82 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P2ConfigurationEditor.java @@ -48,7 +48,6 @@ import javafx.scene.control.SpinnerValueFactory; import javafx.scene.control.TitledPane; import javafx.scene.control.Tooltip; import javafx.scene.layout.GridPane; -import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import org.controlsfx.control.ToggleSwitch; import org.slf4j.Logger; @@ -171,26 +170,8 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor gridPane.getChildren().add(noteLabel); row++; - Label jmbeLabel = new Label("AMBE Audio"); - GridPane.setHalignment(jmbeLabel, HPos.LEFT); - gridPane.add(jmbeLabel, 0, row); - - GridPane.setHalignment(getJmbeAGCButton(), HPos.LEFT); - gridPane.add(getJmbeAGCButton(), 1, row); - - gridPane.add(new Label("Tone Volume:"), 2, row); - - GridPane.setHgrow(getJmbeToneGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeToneGainSlider(), 3, row); - - gridPane.add(new Label("Comfort Noise Volume:"), 4, row); - - GridPane.setHgrow(getJmbeNoiseGainSlider(), Priority.ALWAYS); - gridPane.add(getJmbeNoiseGainSlider(), 5, row); - - - row++; - gridPane.add(getLegacyToneLevelsButton(), 0, row, 6, 1); + addAudioControls(gridPane, row, "AMBE Audio", getJmbeNoiseGainSlider(), getJmbeAGCButton(), + getJmbeToneGainSlider(), getLegacyToneLevelsButton()); mDecoderPane.setContent(gridPane); } @@ -202,7 +183,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor { if(mJmbeAGCButton == null) { - mJmbeAGCButton = new ToggleSwitch("AGC:"); + mJmbeAGCButton = new ToggleSwitch(); mJmbeAGCButton.setTooltip(new Tooltip("Automatic Gain Control to automatically adjust call audio volume")); mJmbeAGCButton.setDisable(true); mJmbeAGCButton.selectedProperty().addListener((o, old, n) -> modifiedProperty().set(true)); @@ -215,7 +196,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor { if(mLegacyToneLevelsButton == null) { - mLegacyToneLevelsButton = new ToggleSwitch("Use legacy tone levels"); + mLegacyToneLevelsButton = new ToggleSwitch(); 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.")); @@ -433,7 +414,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor getTrafficChannelPoolSizeSpinner().setDisable(false); getTrafficChannelPoolSizeSpinner().getValueFactory().setValue(decodeConfig.getTrafficChannelPoolSize()); getJmbeAGCButton().setSelected(decodeConfig.isAGC()); - getJmbeNoiseGainSlider().setValue(decodeConfig.getNoiseGain()); + getJmbeNoiseGainSlider().setValue(decodeConfig.getComfortNoiseGain()); getJmbeToneGainSlider().setValue(decodeConfig.getToneGain()); getLegacyToneLevelsButton().setSelected(decodeConfig.isLegacyToneLevels()); } @@ -480,7 +461,7 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor config.setIgnoreDataCalls(getIgnoreDataCallsButton().isSelected()); config.setTrafficChannelPoolSize(getTrafficChannelPoolSizeSpinner().getValue()); config.setAGC(getJmbeAGCButton().selectedProperty().getValue()); - config.setNoiseGain((float)getJmbeNoiseGainSlider().getValue()); + config.setComfortNoiseGain((float)getJmbeNoiseGainSlider().getValue()); config.setToneGain((float)getJmbeToneGainSlider().getValue()); config.setLegacyToneLevels(getLegacyToneLevelsButton().isSelected()); getItem().setDecodeConfiguration(config); diff --git a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java index 50ac9a16..77cbb70e 100644 --- a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java +++ b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java @@ -571,10 +571,9 @@ public class DecoderFactory { List features = audioModule.getFeatures(); - String legacyToneFeature = "feature_legacy_tone_levels"; - if(features.contains(legacyToneFeature)) + if(features.contains(IAudioCodecV2.FEATURE_LEGACY_TONE_LEVELS)) { - audioModule.setFeature(legacyToneFeature, config.isLegacyToneLevels()); + audioModule.setFeature(IAudioCodecV2.FEATURE_LEGACY_TONE_LEVELS, config.isLegacyToneLevels()); } if(features.contains(IAudioCodecV2.FEATURE_AUTOMATIC_GAIN_CONTROL)) @@ -584,7 +583,7 @@ public class DecoderFactory if(features.contains(IAudioCodecV2.FEATURE_NOISE_GENERATOR_GAIN)) { - audioModule.setFeature(IAudioCodecV2.FEATURE_NOISE_GENERATOR_GAIN, config.getNoiseGain()); + audioModule.setFeature(IAudioCodecV2.FEATURE_NOISE_GENERATOR_GAIN, config.getComfortNoiseGain()); } if(features.contains(IAudioCodecV2.FEATURE_TONE_GENERATOR_GAIN)) @@ -956,7 +955,7 @@ public class DecoderFactory public static void transferJMBESettings(DecodeConfigJMBE from, DecodeConfigJMBE to) { to.setAGC(from.isAGC()); - to.setNoiseGain(from.getNoiseGain()); + to.setComfortNoiseGain(from.getComfortNoiseGain()); to.setToneGain(from.getToneGain()); to.setLegacyToneLevels(from.isLegacyToneLevels()); } diff --git a/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java b/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java index 70b19eb5..25a61af4 100644 --- a/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java +++ b/src/main/java/io/github/dsheirer/module/decode/config/DecodeConfigJMBE.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public abstract class DecodeConfigJMBE extends DecodeConfiguration { + public static float DEFAULT_COMFORT_NOISE_GAIN = 0.05f; + public static float DEFAULT_TONE_GAIN = 1.0f; private boolean mAGC = true; private boolean mLegacyToneLevels; @@ -21,8 +23,8 @@ public abstract class DecodeConfigJMBE extends DecodeConfiguration { mLegacyToneLevels = enabled; } - private float mToneGain = 1.0f; - private float mNoiseGain = 1.0f; + private float mToneGain = DEFAULT_TONE_GAIN; + private float mComfortNoiseGain = DEFAULT_COMFORT_NOISE_GAIN; /** * Automatic Gain Control (AGC) for the JMBE audio codec @@ -78,28 +80,28 @@ public abstract class DecodeConfigJMBE extends DecodeConfiguration * @return noise gain in range 0.0 (no noise) to 1.0 (default noise) */ @JacksonXmlProperty(isAttribute = true, localName = "jmbeNoiseGain", namespace = "http://www.w3.org/2001/XMLSchema-instance") - public float getNoiseGain() + public float getComfortNoiseGain() { - return mNoiseGain; + return mComfortNoiseGain; } /** * Sets the comfort noise insertion gain for the JMBE audio codec * @param gain noise gain in range 0.0 (no noise) to 1.0 (default noise) */ - public void setNoiseGain(float gain) + public void setComfortNoiseGain(float gain) { if(gain > 1.0f) { - mNoiseGain = 1.0f; + mComfortNoiseGain = 1.0f; } else if(gain < 0) { - mNoiseGain = 0; + mComfortNoiseGain = 0; } else { - mNoiseGain = gain; + mComfortNoiseGain = gain; } } } diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DecodeConfigDMR.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DecodeConfigDMR.java index b1f26bdb..afac3c93 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DecodeConfigDMR.java +++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DecodeConfigDMR.java @@ -22,7 +22,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import io.github.dsheirer.module.decode.DecoderType; import io.github.dsheirer.module.decode.config.DecodeConfigJMBE; -import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency; import io.github.dsheirer.module.decode.dmr.message.DMRMessage; import io.github.dsheirer.module.decode.event.DecodeEvent; diff --git a/src/main/java/io/github/dsheirer/module/decode/nxdn/DecodeConfigNXDN.java b/src/main/java/io/github/dsheirer/module/decode/nxdn/DecodeConfigNXDN.java index 7a30884d..5e72453f 100644 --- a/src/main/java/io/github/dsheirer/module/decode/nxdn/DecodeConfigNXDN.java +++ b/src/main/java/io/github/dsheirer/module/decode/nxdn/DecodeConfigNXDN.java @@ -23,7 +23,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import io.github.dsheirer.module.decode.DecoderType; import io.github.dsheirer.module.decode.config.DecodeConfigJMBE; -import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.decode.nxdn.channel.ChannelFrequency; import io.github.dsheirer.module.decode.nxdn.layer3.proprietary.Encoding; import io.github.dsheirer.module.decode.nxdn.layer3.type.TransmissionMode; diff --git a/src/main/java/io/github/dsheirer/module/decode/p25/phase1/DecodeConfigP25.java b/src/main/java/io/github/dsheirer/module/decode/p25/phase1/DecodeConfigP25.java index c6b915dd..30682153 100644 --- a/src/main/java/io/github/dsheirer/module/decode/p25/phase1/DecodeConfigP25.java +++ b/src/main/java/io/github/dsheirer/module/decode/p25/phase1/DecodeConfigP25.java @@ -23,7 +23,6 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import io.github.dsheirer.module.decode.config.DecodeConfigJMBE; -import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")