From d42be9ec8192047df878df3dbabd1c2fdc00cb3b Mon Sep 17 00:00:00 2001 From: Igor Maznitsa Date: Sun, 8 Dec 2024 16:27:58 +0200 Subject: [PATCH] refactoring --- .../zxpoly/components/Motherboard.java | 3 +- .../sound/SoundChannelLowPassFilter.java | 3 + .../zxpoly/ui/CustomIntSlider.java | 100 ++++++++++++++++++ .../igormaznitsa/zxpoly/ui/OptionsPanel.java | 31 +++--- 4 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/CustomIntSlider.java diff --git a/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/Motherboard.java b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/Motherboard.java index 3ca978a7..3e248089 100644 --- a/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/Motherboard.java +++ b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/Motherboard.java @@ -32,6 +32,7 @@ import com.igormaznitsa.zxpoly.components.betadisk.BetaDiscInterface; import com.igormaznitsa.zxpoly.components.sound.Beeper; import com.igormaznitsa.zxpoly.components.sound.CovoxFb; +import com.igormaznitsa.zxpoly.components.sound.SoundChannelLowPassFilter; import com.igormaznitsa.zxpoly.components.sound.TurboSoundNedoPc; import com.igormaznitsa.zxpoly.components.sound.VolumeProfile; import com.igormaznitsa.zxpoly.components.sound.Zx128Ay8910; @@ -128,7 +129,7 @@ public Motherboard( this.boardMode = boardMode; final float lowPassFilter = AppOptions.getInstance().isLpfActive() ? AppOptions.getInstance() - .getLpfValue() / 100.0f : -1.0f; + .getLpfValue() / SoundChannelLowPassFilter.COEFF : SoundChannelLowPassFilter.OFF; LOGGER.info("Low Pass Sound Filter is " + (lowPassFilter < 0 ? "OFF" : lowPassFilter)); this.beeper = diff --git a/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/sound/SoundChannelLowPassFilter.java b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/sound/SoundChannelLowPassFilter.java index 21245966..828368f4 100644 --- a/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/sound/SoundChannelLowPassFilter.java +++ b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/components/sound/SoundChannelLowPassFilter.java @@ -2,6 +2,9 @@ public final class SoundChannelLowPassFilter { + public static final float COEFF = 1000.0f; + public static final float OFF = -1.0f; + private final float alpha1; private final float alpha2; private final int channelIndex; diff --git a/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/CustomIntSlider.java b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/CustomIntSlider.java new file mode 100644 index 00000000..56e051c8 --- /dev/null +++ b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/CustomIntSlider.java @@ -0,0 +1,100 @@ +package com.igormaznitsa.zxpoly.ui; + +import static java.util.Objects.requireNonNull; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.function.IntFunction; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; + +public class CustomIntSlider extends JPanel { + private final JSlider slider; + private final JLabel labelMinIndicator; + private final JLabel labelMaxIndicator; + private final JLabel labelIndicator; + private final IntFunction convertingFunction; + private double value; + + public CustomIntSlider( + final int min, + final int max, + final IntFunction convertingFunction) { + super(new GridBagLayout()); + + this.convertingFunction = requireNonNull(convertingFunction); + + this.slider = new JSlider(JSlider.HORIZONTAL, min, max, min); + this.slider.setPaintTrack(true); + this.slider.setPaintLabels(false); + this.slider.setPaintTicks(false); + + this.labelIndicator = new JLabel(this.valueAsText(min)); + + final GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = 0; + gridBagConstraints.weightx = 1; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + + this.labelMinIndicator = new JLabel(valueAsText(min)); + this.labelMinIndicator.setHorizontalAlignment(JLabel.LEFT); + this.add(this.labelMinIndicator, gridBagConstraints); + + gridBagConstraints.anchor = GridBagConstraints.CENTER; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = 1; + gridBagConstraints.weightx = 1000; + + this.labelIndicator.setHorizontalAlignment(JLabel.CENTER); + this.add(this.labelIndicator, gridBagConstraints); + + gridBagConstraints.anchor = GridBagConstraints.EAST; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = 2; + gridBagConstraints.weightx = 1; + + this.labelMaxIndicator = new JLabel(valueAsText(max)); + this.labelMinIndicator.setHorizontalAlignment(JLabel.RIGHT); + this.add(this.labelMaxIndicator, gridBagConstraints); + + gridBagConstraints.anchor = GridBagConstraints.CENTER; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridx = 0; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.weightx = 1000; + + this.add(this.slider, gridBagConstraints); + + this.slider.addChangeListener(e -> { + this.labelIndicator.setText( + "" + this.valueAsText(this.slider.getValue()) + ""); + }); + } + + @Override + public void setEnabled(final boolean value) { + super.setEnabled(value); + + this.labelMinIndicator.setEnabled(value); + this.labelMaxIndicator.setEnabled(value); + this.labelIndicator.setEnabled(value); + this.slider.setEnabled(value); + } + + public int getValue() { + return this.slider.getValue(); + } + + public void setValue(final int value) { + this.slider.setValue(value); + } + + private String valueAsText(final int value) { + final double doubleValue = this.convertingFunction.apply(value); + return String.format("%.3f", doubleValue); + } + +} diff --git a/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/OptionsPanel.java b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/OptionsPanel.java index fa96253b..c6cab069 100644 --- a/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/OptionsPanel.java +++ b/zxpoly-emul/src/main/java/com/igormaznitsa/zxpoly/ui/OptionsPanel.java @@ -21,6 +21,7 @@ import static javax.swing.BorderFactory.createTitledBorder; import com.igormaznitsa.zxpoly.components.BoardMode; +import com.igormaznitsa.zxpoly.components.sound.SoundChannelLowPassFilter; import com.igormaznitsa.zxpoly.components.sound.VolumeProfile; import com.igormaznitsa.zxpoly.components.video.BorderWidth; import com.igormaznitsa.zxpoly.components.video.VirtualKeyboardLook; @@ -45,7 +46,6 @@ import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextField; @@ -81,7 +81,7 @@ public class OptionsPanel extends JTabbedPane { private JLabel labelBorderWidth; private JLabel labelEmulateFFport; private JCheckBox checkboxActivateLowPassFilter; - private JSlider sliderLowPassFilterValue; + private CustomIntSlider sliderLowPassFilterValue; private JCheckBox checkGrabSound; private JCheckBox checkTryLessResources; private JCheckBox checkInterlacedScan; @@ -126,7 +126,8 @@ public OptionsPanel(final DataContainer dataContainer) { initComponents(); this.comboRomSource.removeAllItems(); - Arrays.stream(RomSource.values()).filter(x -> x != RomSource.UNKNOWN).forEach(x -> this.comboRomSource.addItem(x.getTitle())); + Arrays.stream(RomSource.values()).filter(x -> x != RomSource.UNKNOWN) + .forEach(x -> this.comboRomSource.addItem(x.getTitle())); final List addressList = new ArrayList<>(); @@ -192,7 +193,8 @@ private void fillByDataContainer(final DataContainer data) { this.textFfmpegPath.setText(data.ffmpegPath); this.comboNetAdddr.setSelectedItem(data.inetAddress); this.spinnerFramesPerSec.setValue(data.frameRate); - this.comboRomSource.setSelectedItem(RomSource.findForLink(data.activeRom, RomSource.TEST).getTitle()); + this.comboRomSource.setSelectedItem( + RomSource.findForLink(data.activeRom, RomSource.TEST).getTitle()); this.comboKeyboardLook.setSelectedItem(data.keyboardLook); this.comboVolumeProfile.setSelectedItem(data.volumeProfile); this.comboBorderWidth.setSelectedItem(data.borderWidth); @@ -262,16 +264,17 @@ private void initComponents() { comboTimingProfile = new JComboBox<>(TimingProfile.values()); comboBorderWidth = new JComboBox<>(BorderWidth.values()); textCustomRomPath = new JFilePathTextField(); - textCustomRomPath.setToolTipText("Provided file path overrides selected ROM, if empty then inactive"); + textCustomRomPath.setToolTipText( + "Provided file path overrides selected ROM, if empty then inactive"); labelEmulateFFport = new JLabel(); checkEmulateFFport = new JCheckBox(); checkboxActivateLowPassFilter = new JCheckBox(); - sliderLowPassFilterValue = new JSlider(0, 100); - sliderLowPassFilterValue.setMajorTickSpacing(10); - sliderLowPassFilterValue.setPaintLabels(true); - sliderLowPassFilterValue.setPaintTicks(true); - sliderLowPassFilterValue.setPaintTrack(true); - + sliderLowPassFilterValue = new CustomIntSlider(0, 1000, d -> { + if (d == 0.0d) { + return 0.0d; + } + return (Math.exp((double) d / SoundChannelLowPassFilter.COEFF) - 1) / 1.71828182846d; + }); keySelectorKempstonDown = new KeyCodeChooser(); keySelectorKempstonLeft = new KeyCodeChooser(); keySelectorKempstonUp = new KeyCodeChooser(); @@ -891,7 +894,9 @@ public DataContainer() { public DataContainer(final OptionsPanel optionsPanel) { final RomSource rom = - RomSource.findForTitle(requireNonNull(optionsPanel.comboRomSource.getSelectedItem()).toString(), RomSource.TEST); + RomSource.findForTitle( + requireNonNull(optionsPanel.comboRomSource.getSelectedItem()).toString(), + RomSource.TEST); this.keyboardLook = (VirtualKeyboardLook) optionsPanel.comboKeyboardLook.getSelectedItem(); this.volumeProfile = (VolumeProfile) optionsPanel.comboVolumeProfile.getSelectedItem(); @@ -965,7 +970,7 @@ public void store() { AppOptions.getInstance().setAttributePortFf(this.emulateFFport); AppOptions.getInstance().setKempstonMouseAllowed(this.kempstonMouseAllowed); AppOptions.getInstance() - .setDefaultBoardMode(this.zx128byDefault ? BoardMode.ZX128 : BoardMode.ZXPOLY); + .setDefaultBoardMode(this.zx128byDefault ? BoardMode.ZX128 : BoardMode.ZXPOLY); AppOptions.getInstance().setKempstonVkDown(this.kempstonKeyDown); AppOptions.getInstance().setKempstonVkLeft(this.kempstonKeyLeft);