Revamped equaliser and added to book settings

This commit is contained in:
2018-09-25 16:57:51 +01:00
parent 6adb22b9ac
commit e626da0c5e
11 changed files with 242 additions and 143 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

View File

@@ -48,6 +48,8 @@ public class AudiobookRecorder extends JFrame {
JScrollPane mainScroll; JScrollPane mainScroll;
JDialog equaliserWindow = null;
Book book = null; Book book = null;
JTree bookTree; JTree bookTree;
@@ -1147,6 +1149,10 @@ public class AudiobookRecorder extends JFrame {
prefs.setProperty("book.genre", book.getGenre()); prefs.setProperty("book.genre", book.getGenre());
prefs.setProperty("book.comment", book.getComment()); prefs.setProperty("book.comment", book.getComment());
for (int i = 0; i < 31; i++) {
prefs.setProperty("audio.eq." + i, String.format("%.3f", book.equaliser.getChannel(i)));
}
for (Enumeration<Chapter> o = book.children(); o.hasMoreElements();) { for (Enumeration<Chapter> o = book.children(); o.hasMoreElements();) {
Chapter c = o.nextElement(); Chapter c = o.nextElement();
@@ -1212,6 +1218,14 @@ public class AudiobookRecorder extends JFrame {
book.setGenre(prefs.getProperty("book.genre")); book.setGenre(prefs.getProperty("book.genre"));
book.setComment(prefs.getProperty("book.comment")); book.setComment(prefs.getProperty("book.comment"));
for (int i = 0; i < 31; i++) {
if (prefs.getProperty("audio.eq." + i) == null) {
book.equaliser.setChannel(i, Options.getFloat("audio.eq." + i));
} else {
book.equaliser.setChannel(i, Utils.s2f(prefs.getProperty("audio.eq." + i)));
}
}
bookTreeModel = new DefaultTreeModel(book); bookTreeModel = new DefaultTreeModel(book);
bookTree = new JTree(bookTreeModel); bookTree = new JTree(bookTreeModel);
bookTree.setEditable(true); bookTree.setEditable(true);
@@ -1632,4 +1646,14 @@ public class AudiobookRecorder extends JFrame {
public void alertNoRoomNoise() { public void alertNoRoomNoise() {
JOptionPane.showMessageDialog(this, "You must record room noise\nbefore recording or playback", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this, "You must record room noise\nbefore recording or playback", "Error", JOptionPane.ERROR_MESSAGE);
} }
public void showEqualiser() {
if (equaliserWindow == null) {
equaliserWindow = new JDialog();
equaliserWindow.setTitle("Equaliser");
equaliserWindow.add(book.equaliser);
equaliserWindow.pack();
}
equaliserWindow.setVisible(true);
}
} }

View File

@@ -8,6 +8,7 @@ import java.util.*;
import java.io.*; import java.io.*;
import java.nio.file.*; import java.nio.file.*;
import javax.swing.tree.*; import javax.swing.tree.*;
import davaguine.jeq.core.IIRControls;
public class Book extends DefaultMutableTreeNode { public class Book extends DefaultMutableTreeNode {
@@ -18,9 +19,14 @@ public class Book extends DefaultMutableTreeNode {
ImageIcon icon; ImageIcon icon;
public Equaliser equaliser;
float[] eqChannels = new float[31];
public Book(String bookname) { public Book(String bookname) {
super(bookname); super(bookname);
name = bookname; name = bookname;
equaliser = new Equaliser();
} }
public void setAuthor(String a) { public void setAuthor(String a) {

View File

@@ -0,0 +1,71 @@
package uk.co.majenko.audiobookrecorder;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.nio.file.*;
import javax.swing.tree.*;
import javax.sound.sampled.*;
import davaguine.jeq.core.IIRControls;
public class Equaliser extends JPanel {
EqualiserChannel channels[];
public Equaliser() {
super();
channels = new EqualiserChannel[31];
setLayout(new BorderLayout());
JPanel inner = new JPanel();
inner.setLayout(new FlowLayout());
for (int i = 0; i < 31; i++) {
channels[i] = new EqualiserChannel();
inner.add(channels[i]);
}
add(inner, BorderLayout.CENTER);
JButton smooth = new JButton("Smooth curve");
smooth.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Float ave[] = new Float[31];
for (int i = 1; i < 30; i++) {
ave[i] = (channels[i-1].getValue() + channels[i].getValue() + channels[i+1].getValue()) / 3.0f;
}
for (int i = 1; i < 30; i++) {
channels[i].setValue(ave[i]);
}
}
});
add(smooth, BorderLayout.SOUTH);
}
public float getChannel(int c) {
return channels[c].getValue();
}
public void setChannel(int c, float v) {
channels[c].setValue(v);
}
public void apply(IIRControls c, int chans) {
for (int i = 0; i < 31; i++) {
c.setBandDbValue(i, 0, channels[i].getValue());
if (chans == 2) {
c.setBandDbValue(i, 1, channels[i].getValue());
}
}
}
}

View File

@@ -0,0 +1,78 @@
package uk.co.majenko.audiobookrecorder;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.nio.file.*;
import javax.swing.tree.*;
import javax.sound.sampled.*;
public class EqualiserChannel extends JPanel {
float value;
JSlider slider;
JTextField textbox;
public EqualiserChannel() {
super();
value = 0;
slider = new JSlider(-120, 120, 0);
textbox = new JTextField();
setLayout(new BorderLayout());
slider.setOrientation(SwingConstants.VERTICAL);
add(slider, BorderLayout.CENTER);
textbox = new JTextField("0.0");
add(textbox, BorderLayout.SOUTH);
textbox.setPreferredSize(new Dimension(40, 20));
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
value = (float)slider.getValue() / 10.0f;
textbox.setText(String.format("%.1f", value));
}
});
textbox.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
textbox.selectAll();
}
public void focusLost(FocusEvent e) {
value = Utils.s2f(textbox.getText());
if (value < -12f) value = -12f;
if (value > 12f) value = 12f;
slider.setValue((int)(value * 10));
textbox.setText(String.format("%.1f", value));
}
});
textbox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
value = Utils.s2f(textbox.getText());
if (value < -12f) value = -12f;
if (value > 12f) value = 12f;
slider.setValue((int)(value * 10));
textbox.setText(String.format("%.1f", value));
}
});
}
public float getValue() {
return value;
}
public void setValue(float v) {
value = v;
slider.setValue((int)(value * 10));
textbox.setText(String.format("%.1f", value));
}
}

View File

@@ -26,5 +26,6 @@ public class Icons {
static public final ImageIcon spinner1 = new ImageIcon(Icons.class.getResource("icons/spinner1.png")); static public final ImageIcon spinner1 = new ImageIcon(Icons.class.getResource("icons/spinner1.png"));
static public final ImageIcon spinner2 = new ImageIcon(Icons.class.getResource("icons/spinner2.png")); static public final ImageIcon spinner2 = new ImageIcon(Icons.class.getResource("icons/spinner2.png"));
static public final ImageIcon spinner3 = new ImageIcon(Icons.class.getResource("icons/spinner3.png")); static public final ImageIcon spinner3 = new ImageIcon(Icons.class.getResource("icons/spinner3.png"));
static public final ImageIcon eq = new ImageIcon(Icons.class.getResource("icons/eq.png"));
} }

View File

@@ -0,0 +1,20 @@
package uk.co.majenko.audiobookrecorder;
import javax.swing.*;
public class JSliderOb extends JSlider {
Object object;
public JSliderOb(int a, int b, int c) {
super(a, b, c);
}
public void setObject(Object o) {
object = o;
}
public Object getObject() {
return object;
}
}

View File

@@ -0,0 +1,19 @@
package uk.co.majenko.audiobookrecorder;
import javax.swing.*;
public class JTextFieldOb extends JTextField {
Object object;
public JTextFieldOb(String s) {
super(s);
}
public void setObject(Object o) {
object = o;
}
public Object getObject() {
return object;
}
}

View File

@@ -15,6 +15,7 @@ public class MainToolBar extends JToolBar {
JButton playSentence; JButton playSentence;
JButton playonSentence; JButton playonSentence;
JButton stopPlaying; JButton stopPlaying;
JButton eq;
AudiobookRecorder root; AudiobookRecorder root;
@@ -99,6 +100,20 @@ public class MainToolBar extends JToolBar {
}); });
add(stopPlaying); add(stopPlaying);
addSeparator();
eq = new JButton(Icons.eq);
eq.setToolTipText("Equaliser");
eq.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
root.showEqualiser();
}
});
add(eq);
setFloatable(false); setFloatable(false);
} }

View File

@@ -30,46 +30,11 @@ public class Options extends JDialog {
JCheckBox enableParsing; JCheckBox enableParsing;
JSpinner cacheSize; JSpinner cacheSize;
JSliderOb[] sliders; Equaliser equaliser;
JTextFieldOb[] eqvals;
static HashMap<String, String> defaultPrefs; static HashMap<String, String> defaultPrefs;
static Preferences prefs = null; static Preferences prefs = null;
static class JSliderOb extends JSlider {
Object object;
public JSliderOb(int a, int b, int c) {
super(a, b, c);
}
public void setObject(Object o) {
object = o;
}
public Object getObject() {
return object;
}
}
public class JTextFieldOb extends JTextField {
Object object;
public JTextFieldOb(String s) {
super(s);
}
public void setObject(Object o) {
object = o;
}
public Object getObject() {
return object;
}
}
static class KVPair implements Comparable { static class KVPair implements Comparable {
public String key; public String key;
public String value; public String value;
@@ -311,98 +276,13 @@ public class Options extends JDialog {
tabs.add("Options", optionsPanel); tabs.add("Options", optionsPanel);
equaliser = new Equaliser();
JPanel eqPanel = new JPanel();
eqPanel.setLayout(new GridBagLayout());
constraint.gridx = 0;
constraint.gridy = 0;
sliders = new JSliderOb[31];
eqvals = new JTextFieldOb[31];
for (int i = 0; i < 31; i++) { for (int i = 0; i < 31; i++) {
sliders[i] = new JSliderOb(-120, 120, (int)(Options.getFloat("audio.eq." + i) * 10)); equaliser.setChannel(i, Options.getFloat("audio.eq." + i));
sliders[i].setOrientation(SwingConstants.VERTICAL);
constraint.gridx = i;
constraint.gridy = 0;
eqPanel.add(sliders[i], constraint);
eqvals[i] = new JTextFieldOb(String.format("%.1f", Options.getFloat("audio.eq." + i)));
constraint.gridy = 1;
eqPanel.add(eqvals[i], constraint);
sliders[i].setObject(eqvals[i]);
eqvals[i].setObject(sliders[i]);
eqvals[i].setPreferredSize(new Dimension(40, 20));
sliders[i].addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JSliderOb o = (JSliderOb)e.getSource();
String v = String.format("%.1f", (float)o.getValue() / 10.0f);
JTextFieldOb tf = (JTextFieldOb)o.getObject();
tf.setText(v);
}
});
eqvals[i].addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
JTextFieldOb o = (JTextFieldOb)e.getSource();
o.selectAll();
}
public void focusLost(FocusEvent e) {
JTextFieldOb o = (JTextFieldOb)e.getSource();
String v = o.getText();
float f = Utils.s2f(v);
if (f < -12f) f = -12f;
if (f > 12f) f = 12f;
JSliderOb s = (JSliderOb)o.getObject();
s.setValue((int)(f * 10));
o.setText(String.format("%.1f", f));
}
});
eqvals[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JTextFieldOb o = (JTextFieldOb)e.getSource();
String v = o.getText();
float f = Utils.s2f(v);
if (f < -12f) f = -12f;
if (f > 12f) f = 12f;
JSliderOb s = (JSliderOb)o.getObject();
s.setValue((int)(f * 10));
o.setText(String.format("%.1f", f));
o.selectAll();
}
});
} }
JButton smooth = new JButton("Smooth curve"); tabs.add("EQ", equaliser);
smooth.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Float ave[] = new Float[31];
for (int i = 1; i < 30; i++) {
ave[i] = (Utils.s2f(eqvals[i - 1].getText()) + Utils.s2f(eqvals[i].getText()) + Utils.s2f(eqvals[i + 1].getText())) / 3.0f;
}
for (int i = 1; i < 30; i++) {
eqvals[i].setText(String.format("%.1f", ave[i]));
sliders[i].setValue((int)(ave[i] * 10));
}
}
});
constraint.gridx = 0;
constraint.gridy = 2;
constraint.gridwidth = 4;
eqPanel.add(smooth, constraint);
tabs.add("EQ", eqPanel);
add(tabs, BorderLayout.CENTER); add(tabs, BorderLayout.CENTER);
@@ -704,7 +584,7 @@ public class Options extends JDialog {
set("cache.size", cacheSize.getValue()); set("cache.size", cacheSize.getValue());
for (int i = 0; i < 31; i++) { for (int i = 0; i < 31; i++) {
set("audio.eq." + i, eqvals[i].getText()); set("audio.eq." + i, equaliser.getChannel(i));
} }
savePreferences(); savePreferences();

View File

@@ -420,12 +420,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
EqualizerInputStream eq = new EqualizerInputStream(s, 31); EqualizerInputStream eq = new EqualizerInputStream(s, 31);
AudioFormat format = eq.getFormat(); AudioFormat format = eq.getFormat();
IIRControls controls = eq.getControls(); IIRControls controls = eq.getControls();
for (int i = 0; i < 31; i++) { AudiobookRecorder.window.book.equaliser.apply(controls, format.getChannels());
controls.setBandDbValue(i, 0, Options.getFloat("audio.eq." + i));
if (format.getChannels() == 2) {
controls.setBandDbValue(i, 1, Options.getFloat("audio.eq." + i));
}
}
int frameSize = format.getFrameSize(); int frameSize = format.getFrameSize();
@@ -459,12 +454,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
AudioFormat format = eq.getFormat(); AudioFormat format = eq.getFormat();
IIRControls controls = eq.getControls(); IIRControls controls = eq.getControls();
for (int i = 0; i < 31; i++) { AudiobookRecorder.window.book.equaliser.apply(controls, format.getChannels());
controls.setBandDbValue(i, 0, Options.getFloat("audio.eq." + i));
if (format.getChannels() == 2) {
controls.setBandDbValue(i, 1, Options.getFloat("audio.eq." + i));
}
}
int frameSize = format.getFrameSize(); int frameSize = format.getFrameSize();
@@ -504,12 +494,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
AudioFormat format = eq.getFormat(); AudioFormat format = eq.getFormat();
IIRControls controls = eq.getControls(); IIRControls controls = eq.getControls();
for (int i = 0; i < 31; i++) { AudiobookRecorder.window.book.equaliser.apply(controls, format.getChannels());
controls.setBandDbValue(i, 0, Options.getFloat("audio.eq." + i));
if (format.getChannels() == 2) {
controls.setBandDbValue(i, 1, Options.getFloat("audio.eq." + i));
}
}
int frameSize = format.getFrameSize(); int frameSize = format.getFrameSize();
int length = crossEndOffset - crossStartOffset; int length = crossEndOffset - crossStartOffset;