Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3eb6704f2f | |||
| cd24beb8a6 | |||
| fa287305eb | |||
| 3fb656b693 | |||
| f514993525 | |||
| 81787260c9 | |||
| f9ad396228 | |||
| 8976f2e359 | |||
| 187c3edaf6 |
@@ -1 +1 @@
|
||||
version=0.1.9
|
||||
version=0.2.0
|
||||
|
||||
BIN
resources/uk/co/majenko/audiobookrecorder/icons/cut.png
Normal file
BIN
resources/uk/co/majenko/audiobookrecorder/icons/cut.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 674 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
resources/uk/co/majenko/audiobookrecorder/icons/do-cut.png
Normal file
BIN
resources/uk/co/majenko/audiobookrecorder/icons/do-cut.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 576 B |
BIN
resources/uk/co/majenko/audiobookrecorder/icons/play-to.png
Normal file
BIN
resources/uk/co/majenko/audiobookrecorder/icons/play-to.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 752 B |
BIN
resources/uk/co/majenko/audiobookrecorder/icons/split.png
Normal file
BIN
resources/uk/co/majenko/audiobookrecorder/icons/split.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 B |
@@ -795,7 +795,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
||||
public FontUIResource getControlTextFont() {
|
||||
if (controlFont == null) {
|
||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||
controlFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
||||
controlFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||
} else {
|
||||
controlFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||
}
|
||||
@@ -806,7 +806,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
||||
public FontUIResource getSystemTextFont() {
|
||||
if (systemFont == null) {
|
||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||
systemFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
||||
systemFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||
} else {
|
||||
systemFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||
}
|
||||
@@ -817,7 +817,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
||||
public FontUIResource getUserTextFont() {
|
||||
if (userFont == null) {
|
||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||
userFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
||||
userFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||
} else {
|
||||
userFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||
}
|
||||
@@ -828,7 +828,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
||||
public FontUIResource getMenuTextFont() {
|
||||
if (menuFont == null) {
|
||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||
menuFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
||||
menuFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||
} else {
|
||||
menuFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||
}
|
||||
@@ -839,9 +839,9 @@ public abstract class AbstractTheme extends MetalTheme {
|
||||
public FontUIResource getWindowTitleFont() {
|
||||
if (windowTitleFont == null) {
|
||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||
windowTitleFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
||||
windowTitleFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||
} else {
|
||||
windowTitleFont = new FontUIResource(DIALOG, Font.BOLD, 12);
|
||||
windowTitleFont = new FontUIResource(DIALOG, Font.PLAIN, 12); // bold
|
||||
}
|
||||
}
|
||||
return windowTitleFont;
|
||||
@@ -850,7 +850,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
||||
public FontUIResource getSubTextFont() {
|
||||
if (smallFont == null) {
|
||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||
smallFont = new FontUIResource(DIALOG, Font.BOLD, 12);
|
||||
smallFont = new FontUIResource(DIALOG, Font.PLAIN, 12); // bold
|
||||
} else {
|
||||
smallFont = new FontUIResource(DIALOG, Font.PLAIN, 10);
|
||||
}
|
||||
|
||||
@@ -125,11 +125,11 @@ public class HiFiDefaultTheme extends AbstractTheme {
|
||||
tooltipForegroundColor = white;
|
||||
tooltipBackgroundColor = new ColorUIResource(24, 24, 24);
|
||||
|
||||
controlFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
||||
systemFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
||||
userFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
||||
menuFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
||||
windowTitleFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
||||
controlFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||
systemFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||
userFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||
menuFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||
windowTitleFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||
smallFont = new FontUIResource("Dialog", Font.PLAIN, 10);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,18 +42,18 @@ public class HiFiLookAndFeel extends AbstractLookAndFeel {
|
||||
private static final Properties giantFontProps = new Properties();
|
||||
|
||||
static {
|
||||
smallFontProps.setProperty("controlTextFont", "Dialog bold 10");
|
||||
smallFontProps.setProperty("systemTextFont", "Dialog bold 10");
|
||||
smallFontProps.setProperty("controlTextFont", "Dialog 10"); // bold
|
||||
smallFontProps.setProperty("systemTextFont", "Dialog 10"); // bold
|
||||
smallFontProps.setProperty("userTextFont", "Dialog 10");
|
||||
smallFontProps.setProperty("menuTextFont", "Dialog bold 10");
|
||||
smallFontProps.setProperty("windowTitleFont", "Dialog bold 10");
|
||||
smallFontProps.setProperty("menuTextFont", "Dialog 10"); // bold
|
||||
smallFontProps.setProperty("windowTitleFont", "Dialog 10"); // bold
|
||||
smallFontProps.setProperty("subTextFont", "Dialog 8");
|
||||
|
||||
largeFontProps.setProperty("controlTextFont", "Dialog bold 14");
|
||||
largeFontProps.setProperty("systemTextFont", "Dialog bold 14");
|
||||
largeFontProps.setProperty("userTextFont", "Dialog bold 14");
|
||||
largeFontProps.setProperty("menuTextFont", "Dialog bold 14");
|
||||
largeFontProps.setProperty("windowTitleFont", "Dialog bold 14");
|
||||
largeFontProps.setProperty("controlTextFont", "Dialog 14"); // bold
|
||||
largeFontProps.setProperty("systemTextFont", "Dialog 14"); // bold
|
||||
largeFontProps.setProperty("userTextFont", "Dialog 14"); // bold
|
||||
largeFontProps.setProperty("menuTextFont", "Dialog 14"); // bold
|
||||
largeFontProps.setProperty("windowTitleFont", "Dialog 14"); // bold
|
||||
largeFontProps.setProperty("subTextFont", "Dialog 12");
|
||||
|
||||
giantFontProps.setProperty("controlTextFont", "Dialog 18");
|
||||
|
||||
@@ -30,7 +30,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
|
||||
// Settings - tweakable
|
||||
|
||||
public static final int PLAYBACK_CHUNK_SIZE = 16384;
|
||||
public static final int PLAYBACK_CHUNK_SIZE = 1024;
|
||||
|
||||
public static final String SPHINX_MODEL = "resource:/edu/cmu/sphinx/models/en-us/en-us";
|
||||
|
||||
@@ -103,6 +103,9 @@ public class AudiobookRecorder extends JFrame {
|
||||
JButtonSpacePlay reprocessAudioFFT;
|
||||
JButtonSpacePlay reprocessAudioPeak;
|
||||
JButtonSpacePlay normalizeAudio;
|
||||
JToggleButtonSpacePlay selectSplitMode;
|
||||
JToggleButtonSpacePlay selectCutMode;
|
||||
JButtonSpacePlay doCutSplit;
|
||||
|
||||
JComboBox<KVPair<String,String>> effectChain;
|
||||
|
||||
@@ -112,6 +115,8 @@ public class AudiobookRecorder extends JFrame {
|
||||
|
||||
SourceDataLine play = null;
|
||||
|
||||
boolean effectsEnabled = true;
|
||||
|
||||
public TargetDataLine microphone = null;
|
||||
public AudioInputStream microphoneStream = null;
|
||||
|
||||
@@ -392,7 +397,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedSentence != null) {
|
||||
selectedSentence.autoTrimSampleFFT();
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
||||
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
||||
postSentenceGap.setValue(selectedSentence.getPostGap());
|
||||
@@ -405,7 +410,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedSentence != null) {
|
||||
selectedSentence.autoTrimSamplePeak();
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
||||
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
||||
postSentenceGap.setValue(selectedSentence.getPostGap());
|
||||
@@ -418,11 +423,28 @@ public class AudiobookRecorder extends JFrame {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedSentence != null) {
|
||||
selectedSentence.normalize();
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
selectSplitMode = new JToggleButtonSpacePlay(Icons.split, "Toggle split mode", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
toggleSplitMode();
|
||||
}
|
||||
});
|
||||
|
||||
selectCutMode = new JToggleButtonSpacePlay(Icons.cut, "Toggle cut mode", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
toggleCutMode();
|
||||
}
|
||||
});
|
||||
|
||||
doCutSplit = new JButtonSpacePlay(Icons.docut, "Perform cut or split", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
executeCutOrSplit();
|
||||
}
|
||||
});
|
||||
|
||||
postSentenceGap = new JSpinner(new SteppedNumericSpinnerModel(0, 5000, 100, 0));
|
||||
postSentenceGap.setPreferredSize(new Dimension(50, 20));
|
||||
@@ -444,7 +466,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
JSpinner ob = (JSpinner)e.getSource();
|
||||
if (selectedSentence != null) {
|
||||
selectedSentence.setGain((Integer)ob.getValue() / 100d);
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -487,6 +509,11 @@ public class AudiobookRecorder extends JFrame {
|
||||
gainPercent.setEnabled(!selectedSentence.isLocked());
|
||||
reprocessAudioFFT.setEnabled(!selectedSentence.isLocked());
|
||||
reprocessAudioPeak.setEnabled(!selectedSentence.isLocked());
|
||||
selectCutMode.setEnabled(!selectedSentence.isLocked());
|
||||
selectSplitMode.setEnabled(!selectedSentence.isLocked());
|
||||
doCutSplit.setEnabled(false);
|
||||
selectCutMode.setSelected(false);
|
||||
selectSplitMode.setSelected(false);
|
||||
|
||||
bookTreeModel.reload(selectedSentence);
|
||||
}
|
||||
@@ -554,13 +581,16 @@ public class AudiobookRecorder extends JFrame {
|
||||
int i = effectChain.getSelectedIndex();
|
||||
KVPair<String, String> p = effectChain.getItemAt(i);
|
||||
if (p == null) return;
|
||||
CacheManager.removeFromCache(selectedSentence);
|
||||
selectedSentence.setEffectChain(p.getKey());
|
||||
updateWaveform();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
controlsBottom.add(selectSplitMode);
|
||||
controlsBottom.add(selectCutMode);
|
||||
controlsBottom.add(doCutSplit);
|
||||
|
||||
sampleControl.add(controlsTop, BorderLayout.NORTH);
|
||||
sampleControl.add(controlsLeft, BorderLayout.WEST);
|
||||
sampleControl.add(controlsRight, BorderLayout.EAST);
|
||||
@@ -955,6 +985,72 @@ public class AudiobookRecorder extends JFrame {
|
||||
}
|
||||
});
|
||||
|
||||
JMenu setGapType = new JMenu("Post-gap Type...");
|
||||
|
||||
String sentenceText = " Sentence";
|
||||
String continuationText = " Continuation";
|
||||
String paragraphText = " Paragraph";
|
||||
String sectionText = " Section";
|
||||
|
||||
if (s.getPostGapType().equals("sentence")) {
|
||||
sentenceText = "\u2713 Sentence";
|
||||
} else if (s.getPostGapType().equals("continuation")) {
|
||||
continuationText = "\u2713 Continuation";
|
||||
} else if (s.getPostGapType().equals("paragraph")) {
|
||||
paragraphText = "\u2713 Paragraph";
|
||||
} else if (s.getPostGapType().equals("section")) {
|
||||
sectionText = "\u2713 Section";
|
||||
}
|
||||
|
||||
JMenuObject2 gapTypeSentence = new JMenuObject2(sentenceText, s, "sentence", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuObject2 o = (JMenuObject2)e.getSource();
|
||||
Sentence sent = (Sentence)o.getObject1();
|
||||
String type = (String)o.getObject2();
|
||||
sent.setPostGapType(type);
|
||||
sent.setPostGap(Options.getInteger("catenation.post-sentence"));
|
||||
bookTreeModel.reload(sent);
|
||||
}
|
||||
});
|
||||
setGapType.add(gapTypeSentence);
|
||||
|
||||
JMenuObject2 gapTypeContinuation = new JMenuObject2(continuationText, s, "continuation", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuObject2 o = (JMenuObject2)e.getSource();
|
||||
Sentence sent = (Sentence)o.getObject1();
|
||||
String type = (String)o.getObject2();
|
||||
sent.setPostGapType(type);
|
||||
sent.setPostGap(Options.getInteger("catenation.short-sentence"));
|
||||
bookTreeModel.reload(sent);
|
||||
}
|
||||
});
|
||||
setGapType.add(gapTypeContinuation);
|
||||
|
||||
JMenuObject2 gapTypeParagraph = new JMenuObject2(paragraphText, s, "paragraph", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuObject2 o = (JMenuObject2)e.getSource();
|
||||
Sentence sent = (Sentence)o.getObject1();
|
||||
String type = (String)o.getObject2();
|
||||
sent.setPostGapType(type);
|
||||
sent.setPostGap(Options.getInteger("catenation.post-paragraph"));
|
||||
bookTreeModel.reload(sent);
|
||||
}
|
||||
});
|
||||
setGapType.add(gapTypeParagraph);
|
||||
|
||||
JMenuObject2 gapTypeSection = new JMenuObject2(sectionText, s, "section", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuObject2 o = (JMenuObject2)e.getSource();
|
||||
Sentence sent = (Sentence)o.getObject1();
|
||||
String type = (String)o.getObject2();
|
||||
sent.setPostGapType(type);
|
||||
sent.setPostGap(Options.getInteger("catenation.post-section"));
|
||||
bookTreeModel.reload(sent);
|
||||
}
|
||||
});
|
||||
setGapType.add(gapTypeSection);
|
||||
|
||||
|
||||
|
||||
JMenuObject ins = new JMenuObject("Insert phrase above", s, new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -1038,6 +1134,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
menu.add(moveUp);
|
||||
menu.add(moveDown);
|
||||
menu.add(moveMenu);
|
||||
menu.add(setGapType);
|
||||
menu.addSeparator();
|
||||
menu.add(edit);
|
||||
menu.add(external);
|
||||
@@ -1068,26 +1165,36 @@ public class AudiobookRecorder extends JFrame {
|
||||
JMenuObject peak = new JMenuObject("Auto-trim all (Peak)", c, new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuObject o = (JMenuObject)e.getSource();
|
||||
Chapter c = (Chapter)o.getObject();
|
||||
for (Enumeration s = c.children(); s.hasMoreElements();) {
|
||||
Sentence snt = (Sentence)s.nextElement();
|
||||
if (!snt.isLocked()) {
|
||||
snt.autoTrimSamplePeak();
|
||||
}
|
||||
}
|
||||
Chapter chap = (Chapter)o.getObject();
|
||||
|
||||
ProgressDialog ed = new ProgressDialog("Auto-trimming " + chap.getName());
|
||||
|
||||
AutoTrimThread t = new AutoTrimThread(chap, ed, AutoTrimThread.Peak);
|
||||
Thread nt = new Thread(t);
|
||||
nt.start();
|
||||
ed.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
JMenuObject fft = new JMenuObject("Auto-trim all (FFT)", c, new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuObject o = (JMenuObject)e.getSource();
|
||||
Chapter chap = (Chapter)o.getObject();
|
||||
|
||||
ProgressDialog ed = new ProgressDialog("Auto-trimming " + chap.getName());
|
||||
|
||||
AutoTrimThread t = new AutoTrimThread(chap, ed, AutoTrimThread.FFT);
|
||||
Thread nt = new Thread(t);
|
||||
nt.start();
|
||||
ed.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
JMenuObject resetChapterGaps = new JMenuObject("Reset post gaps", c, new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuObject o = (JMenuObject)e.getSource();
|
||||
Chapter c = (Chapter)o.getObject();
|
||||
for (Enumeration s = c.children(); s.hasMoreElements();) {
|
||||
Sentence snt = (Sentence)s.nextElement();
|
||||
if (!snt.isLocked()) {
|
||||
snt.autoTrimSampleFFT();
|
||||
}
|
||||
}
|
||||
c.resetPostGaps();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1224,12 +1331,16 @@ public class AudiobookRecorder extends JFrame {
|
||||
|
||||
JMenuObject normalizeAll = new JMenuObject("Normalize chapter", c, new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
JMenuObject o = (JMenuObject)e.getSource();
|
||||
Chapter c = (Chapter)o.getObject();
|
||||
for (Enumeration s = c.children(); s.hasMoreElements();) {
|
||||
Sentence snt = (Sentence)s.nextElement();
|
||||
snt.normalize();
|
||||
}
|
||||
Chapter chap = (Chapter)o.getObject();
|
||||
|
||||
ProgressDialog ed = new ProgressDialog("Normalizing " + chap.getName());
|
||||
|
||||
NormalizeThread t = new NormalizeThread(chap, ed);
|
||||
Thread nt = new Thread(t);
|
||||
nt.start();
|
||||
ed.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1258,6 +1369,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
|
||||
menu.add(convertAll);
|
||||
menu.add(normalizeAll);
|
||||
menu.add(resetChapterGaps);
|
||||
menu.addSeparator();
|
||||
menu.add(moveUp);
|
||||
menu.add(moveDown);
|
||||
@@ -1346,6 +1458,17 @@ public class AudiobookRecorder extends JFrame {
|
||||
});
|
||||
menu.add(editData);
|
||||
|
||||
JMenuObject resetBookGaps = new JMenuObject("Reset all post gaps", book, new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
for (Enumeration ch = book.children(); ch.hasMoreElements();) {
|
||||
Chapter chap = (Chapter)ch.nextElement();
|
||||
chap.resetPostGaps();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
menu.add(resetBookGaps);
|
||||
|
||||
menu.show(bookTree, e.getX(), e.getY());
|
||||
}
|
||||
|
||||
@@ -1423,6 +1546,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
if (lastLeaf instanceof Sentence) {
|
||||
Sentence lastSentence = (Sentence)lastLeaf;
|
||||
lastSentence.setPostGap(Options.getInteger("catenation.short-sentence"));
|
||||
lastSentence.setPostGapType("continuation");
|
||||
}
|
||||
|
||||
Sentence s = new Sentence();
|
||||
@@ -1473,6 +1597,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
if (lastLeaf instanceof Sentence) {
|
||||
Sentence lastSentence = (Sentence)lastLeaf;
|
||||
lastSentence.setPostGap(Options.getInteger("catenation.post-paragraph"));
|
||||
lastSentence.setPostGapType("paragraph");
|
||||
}
|
||||
|
||||
Sentence s = new Sentence();
|
||||
@@ -1522,6 +1647,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
if (lastLeaf instanceof Sentence) {
|
||||
Sentence lastSentence = (Sentence)lastLeaf;
|
||||
lastSentence.setPostGap(Options.getInteger("catenation.post-section"));
|
||||
lastSentence.setPostGapType("section");
|
||||
}
|
||||
|
||||
Sentence s = new Sentence();
|
||||
@@ -1571,6 +1697,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
if (lastLeaf instanceof Sentence) {
|
||||
Sentence lastSentence = (Sentence)lastLeaf;
|
||||
lastSentence.setPostGap(Options.getInteger("catenation.post-sentence"));
|
||||
lastSentence.setPostGapType("sentence");
|
||||
}
|
||||
|
||||
Sentence s = new Sentence();
|
||||
@@ -1696,6 +1823,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
prefs.setProperty(String.format("%s.sentence.%08d.attention", keybase, i), snt.getAttentionFlag() ? "true" : "false");
|
||||
prefs.setProperty(String.format("%s.sentence.%08d.gain", keybase, i), String.format("%.8f", snt.getGain()));
|
||||
prefs.setProperty(String.format("%s.sentence.%08d.effect", keybase, i), snt.getEffectChain());
|
||||
prefs.setProperty(String.format("%s.sentence.%08d.gaptype", keybase, i), snt.getPostGapType());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -1704,13 +1832,14 @@ public class AudiobookRecorder extends JFrame {
|
||||
try {
|
||||
fos = new FileOutputStream(config);
|
||||
prefs.storeToXML(fos, "Audiobook Recorder Description");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (Exception e) {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1798,7 +1927,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
if (n instanceof Sentence) {
|
||||
Sentence s = (Sentence)n;
|
||||
selectedSentence = s;
|
||||
sampleWaveform.setData(s.getDoubleAudioData());
|
||||
sampleWaveform.setData(s.getDoubleAudioData(effectsEnabled));
|
||||
sampleWaveform.setMarkers(s.getStartOffset(), s.getEndOffset());
|
||||
s.updateCrossings();
|
||||
sampleWaveform.setAltMarkers(s.getStartCrossing(), s.getEndCrossing());
|
||||
@@ -1813,6 +1942,11 @@ public class AudiobookRecorder extends JFrame {
|
||||
gainPercent.setEnabled(!s.isLocked());
|
||||
reprocessAudioFFT.setEnabled(!s.isLocked());
|
||||
reprocessAudioPeak.setEnabled(!s.isLocked());
|
||||
selectCutMode.setEnabled(!s.isLocked());
|
||||
selectSplitMode.setEnabled(!s.isLocked());
|
||||
doCutSplit.setEnabled(false);
|
||||
selectCutMode.setSelected(false);
|
||||
selectSplitMode.setSelected(false);
|
||||
} else {
|
||||
selectedSentence = null;
|
||||
sampleWaveform.clearData();
|
||||
@@ -1820,6 +1954,11 @@ public class AudiobookRecorder extends JFrame {
|
||||
gainPercent.setValue(100);
|
||||
locked.setSelected(false);
|
||||
attention.setSelected(false);
|
||||
selectCutMode.setEnabled(false);
|
||||
selectSplitMode.setEnabled(false);
|
||||
doCutSplit.setEnabled(false);
|
||||
selectCutMode.setSelected(false);
|
||||
selectSplitMode.setSelected(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1861,6 +2000,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.audition.sentence.%08d.attention", i))));
|
||||
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.audition.sentence.%08d.gain", i))));
|
||||
s.setEffectChain(prefs.getProperty(String.format("chapter.audition.sentence.%08d.effect", i)));
|
||||
s.setPostGapType(prefs.getProperty(String.format("chapter.audition.sentence.%08d.gaptype", i)));
|
||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||
}
|
||||
|
||||
@@ -1882,6 +2022,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.open.sentence.%08d.attention", i))));
|
||||
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.open.sentence.%08d.gain", i))));
|
||||
s.setEffectChain(prefs.getProperty(String.format("chapter.open.sentence.%08d.effect", i)));
|
||||
s.setPostGapType(prefs.getProperty(String.format("chapter.open.sentence.%08d.gaptype", i)));
|
||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||
}
|
||||
|
||||
@@ -1909,6 +2050,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.attention", cno, i))));
|
||||
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.gain", cno, i))));
|
||||
s.setEffectChain(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.effect", cno, i)));
|
||||
s.setPostGapType(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.gaptype", cno, i)));
|
||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||
}
|
||||
}
|
||||
@@ -1931,6 +2073,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.close.sentence.%08d.attention", i))));
|
||||
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.close.sentence.%08d.gain", i))));
|
||||
s.setEffectChain(prefs.getProperty(String.format("chapter.close.sentence.%08d.effect", i)));
|
||||
s.setPostGapType(prefs.getProperty(String.format("chapter.close.sentence.%08d.gaptype", i)));
|
||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||
}
|
||||
|
||||
@@ -2045,9 +2188,10 @@ public class AudiobookRecorder extends JFrame {
|
||||
play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
||||
play.open(format);
|
||||
play.start();
|
||||
play.drain();
|
||||
|
||||
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
|
||||
data = s.getPCMData();
|
||||
data = s.getPCMData(effectsEnabled);
|
||||
for (int pos = 0; pos < data.length; pos += PLAYBACK_CHUNK_SIZE) {
|
||||
sampleWaveform.setPlayMarker(pos / format.getFrameSize());
|
||||
int l = data.length - pos;
|
||||
@@ -2068,6 +2212,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
play.close();
|
||||
}
|
||||
play = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2076,6 +2221,72 @@ public class AudiobookRecorder extends JFrame {
|
||||
playingThread.start();
|
||||
}
|
||||
|
||||
class NormalizeThread implements Runnable {
|
||||
ProgressDialog dialog;
|
||||
Chapter chapter;
|
||||
|
||||
public NormalizeThread(Chapter c, ProgressDialog e) {
|
||||
super();
|
||||
dialog = e;
|
||||
chapter = c;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void run() {
|
||||
|
||||
int numKids = chapter.getChildCount();
|
||||
int kidCount = 0;
|
||||
for (Enumeration s = chapter.children(); s.hasMoreElements();) {
|
||||
kidCount++;
|
||||
dialog.setProgress(kidCount * 2000 / numKids);
|
||||
Sentence snt = (Sentence)s.nextElement();
|
||||
snt.normalize();
|
||||
}
|
||||
|
||||
dialog.closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
class AutoTrimThread implements Runnable {
|
||||
ProgressDialog dialog;
|
||||
Chapter chapter;
|
||||
int type;
|
||||
|
||||
public final static int FFT = 0;
|
||||
public final static int Peak = 1;
|
||||
|
||||
public AutoTrimThread(Chapter c, ProgressDialog e, int t) {
|
||||
super();
|
||||
dialog = e;
|
||||
chapter = c;
|
||||
type = t;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void run() {
|
||||
|
||||
int numKids = chapter.getChildCount();
|
||||
int kidCount = 0;
|
||||
for (Enumeration s = chapter.children(); s.hasMoreElements();) {
|
||||
kidCount++;
|
||||
dialog.setProgress(kidCount * 2000 / numKids);
|
||||
Sentence snt = (Sentence)s.nextElement();
|
||||
switch (type) {
|
||||
case FFT:
|
||||
snt.autoTrimSampleFFT();
|
||||
break;
|
||||
case Peak:
|
||||
snt.autoTrimSamplePeak();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dialog.closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ExportThread implements Runnable {
|
||||
ProgressDialog exportDialog;
|
||||
Chapter chapter;
|
||||
@@ -2117,6 +2328,82 @@ public class AudiobookRecorder extends JFrame {
|
||||
}
|
||||
|
||||
|
||||
public void playToSelectedSentence() {
|
||||
if (selectedSentence == null) return;
|
||||
if (playing != null) return;
|
||||
if (getNoiseFloor() == 0) {
|
||||
alertNoRoomNoise();
|
||||
return;
|
||||
}
|
||||
playing = selectedSentence;
|
||||
|
||||
playingThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
Sentence s = playing;
|
||||
byte[] data;
|
||||
|
||||
try {
|
||||
|
||||
AudioFormat sampleformat = s.getAudioFormat();
|
||||
AudioFormat format = new AudioFormat(sampleformat.getSampleRate(), 16, 2, true, false);
|
||||
|
||||
play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
||||
play.open(format);
|
||||
play.start();
|
||||
play.drain();
|
||||
|
||||
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
|
||||
data = s.getPCMData(effectsEnabled);
|
||||
|
||||
int startPos = 0;
|
||||
int endPos = data.length / format.getFrameSize();
|
||||
|
||||
//foobar
|
||||
if (selectSplitMode.isSelected()) {
|
||||
endPos = sampleWaveform.getCutStart() - selectedSentence.getStartCrossing();
|
||||
if (endPos < 0) endPos = 0;
|
||||
} else if (selectCutMode.isSelected()) {
|
||||
startPos = sampleWaveform.getCutStart() - selectedSentence.getStartCrossing();;
|
||||
endPos = sampleWaveform.getCutEnd() - selectedSentence.getStartCrossing();;
|
||||
if (startPos < 0) startPos = 0;
|
||||
if (endPos < 0) endPos = 0;
|
||||
}
|
||||
|
||||
startPos *= format.getFrameSize();
|
||||
endPos *= format.getFrameSize();
|
||||
|
||||
if (startPos > data.length) startPos = data.length;
|
||||
if (endPos > data.length) endPos = data.length;
|
||||
|
||||
for (int pos = startPos; pos < endPos; pos += PLAYBACK_CHUNK_SIZE) {
|
||||
sampleWaveform.setPlayMarker(pos / format.getFrameSize());
|
||||
int l = data.length - pos;
|
||||
if (l > PLAYBACK_CHUNK_SIZE) l = PLAYBACK_CHUNK_SIZE;
|
||||
play.write(data, pos, l);
|
||||
}
|
||||
|
||||
play.drain();
|
||||
play.stop();
|
||||
play.close();
|
||||
play = null;
|
||||
playing = null;
|
||||
} catch (Exception e) {
|
||||
playing = null;
|
||||
if (play != null) {
|
||||
play.drain();
|
||||
play.stop();
|
||||
play.close();
|
||||
}
|
||||
play = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
playingThread.setDaemon(true);
|
||||
playingThread.start();
|
||||
}
|
||||
|
||||
public void playFromSelectedSentence() {
|
||||
if (selectedSentence == null) return;
|
||||
if (playing != null) return;
|
||||
@@ -2138,6 +2425,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
||||
play.open(format);
|
||||
play.start();
|
||||
play.drain();
|
||||
|
||||
while (playing != null) {
|
||||
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
|
||||
@@ -2152,17 +2440,17 @@ public class AudiobookRecorder extends JFrame {
|
||||
data = getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter")));
|
||||
play.write(data, 0, data.length);
|
||||
}
|
||||
data = s.getPCMData();
|
||||
data = s.getPCMData(effectsEnabled);
|
||||
DefaultMutableTreeNode next = s.getNextSibling();
|
||||
// if (next != null) {
|
||||
// Thread t = new Thread(new Runnable() {
|
||||
// public void run() {
|
||||
// Sentence ns = (Sentence)next;
|
||||
// ns.getProcessedAudioData(); // Cache it
|
||||
// }
|
||||
// });
|
||||
// t.start();
|
||||
// }
|
||||
if (next != null) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
Sentence ns = (Sentence)next;
|
||||
ns.getProcessedAudioData(effectsEnabled); // Cache it
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
for (int pos = 0; pos < data.length; pos += PLAYBACK_CHUNK_SIZE) {
|
||||
sampleWaveform.setPlayMarker(pos / format.getFrameSize());
|
||||
int l = data.length - pos;
|
||||
@@ -2182,6 +2470,12 @@ public class AudiobookRecorder extends JFrame {
|
||||
play.write(data, 0, data.length);
|
||||
playing = null;
|
||||
} else {
|
||||
play.drain();
|
||||
play.stop();
|
||||
play.close();
|
||||
play.open(format);
|
||||
play.start();
|
||||
play.drain();
|
||||
data = getRoomNoise(s.getPostGap());
|
||||
play.write(data, 0, data.length);
|
||||
}
|
||||
@@ -2202,6 +2496,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
play.close();
|
||||
}
|
||||
play = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2409,6 +2704,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
try {
|
||||
Files.copy(srcFile.toPath(), dstFile.toPath());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2536,6 +2832,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
f.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
pd.closeDialog();
|
||||
}
|
||||
@@ -2686,7 +2983,7 @@ public class AudiobookRecorder extends JFrame {
|
||||
if (rawAudio.isSelected()) {
|
||||
sampleWaveform.setData(selectedSentence.getRawAudioData());
|
||||
} else {
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3012,4 +3309,92 @@ public class AudiobookRecorder extends JFrame {
|
||||
state = STOPPING;
|
||||
}
|
||||
|
||||
public void toggleSplitMode() {
|
||||
selectCutMode.setSelected(false);
|
||||
if (selectedSentence != null) {
|
||||
sampleWaveform.setDisplaySplit(selectSplitMode.isSelected());
|
||||
}
|
||||
doCutSplit.setEnabled(selectSplitMode.isSelected());
|
||||
toolBar.enablePlayTo(selectSplitMode.isSelected());
|
||||
}
|
||||
|
||||
public void toggleCutMode() {
|
||||
selectSplitMode.setSelected(false);
|
||||
if (selectedSentence != null) {
|
||||
sampleWaveform.setDisplayCut(selectCutMode.isSelected());
|
||||
}
|
||||
doCutSplit.setEnabled(selectCutMode.isSelected());
|
||||
toolBar.enablePlayTo(selectCutMode.isSelected());
|
||||
}
|
||||
|
||||
public void doCut(int start, int end) {
|
||||
try {
|
||||
double[][] samples = selectedSentence.getRawAudioData();
|
||||
double[][] croppedSamples = new double[samples.length - (end - start)][2];
|
||||
|
||||
int a = 0;
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
if ((i < start) || (i > end)) {
|
||||
croppedSamples[a++] = samples[i];
|
||||
}
|
||||
}
|
||||
selectedSentence.writeAudioData(croppedSamples);
|
||||
selectedSentence.autoTrimSample();
|
||||
updateWaveform();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void doSplit(int at) {
|
||||
try {
|
||||
Sentence newSentence = selectedSentence.cloneSentence();
|
||||
Chapter c = (Chapter)selectedSentence.getParent();
|
||||
int idx = bookTreeModel.getIndexOfChild(c, selectedSentence);
|
||||
bookTreeModel.insertNodeInto(newSentence, c, idx);
|
||||
|
||||
double[][] samples = selectedSentence.getRawAudioData();
|
||||
double[][] startSamples = new double[at][2];
|
||||
double[][] endSamples = new double[samples.length - at][2];
|
||||
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
if (i < at) {
|
||||
startSamples[a++] = samples[i];
|
||||
} else {
|
||||
endSamples[b++] = samples[i];
|
||||
}
|
||||
}
|
||||
|
||||
newSentence.writeAudioData(startSamples);
|
||||
selectedSentence.writeAudioData(endSamples);
|
||||
selectedSentence.autoTrimSample();
|
||||
newSentence.autoTrimSample();
|
||||
updateWaveform();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void executeCutOrSplit() {
|
||||
int start = sampleWaveform.getCutStart();
|
||||
int end = sampleWaveform.getCutEnd();
|
||||
if (selectCutMode.isSelected()) {
|
||||
doCut(start, end);
|
||||
} else if (selectSplitMode.isSelected()) {
|
||||
doSplit(start);
|
||||
}
|
||||
selectCutMode.setSelected(false);
|
||||
selectSplitMode.setSelected(false);
|
||||
toolBar.enablePlayTo(false);
|
||||
doCutSplit.setEnabled(false);
|
||||
}
|
||||
|
||||
public void setEffectsEnabled(boolean b) {
|
||||
effectsEnabled = b;
|
||||
System.err.println("Effects Enabled: " + b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ package uk.co.majenko.audiobookrecorder;
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.*;
|
||||
import java.awt.*;
|
||||
import javax.swing.border.*;
|
||||
|
||||
public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
||||
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
JLabel ret = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
ret.setIconTextGap(0);
|
||||
ret.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
if (value instanceof Sentence) {
|
||||
Sentence s = (Sentence)value;
|
||||
|
||||
@@ -39,6 +42,28 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
||||
|
||||
ret.setIcon(icn);
|
||||
|
||||
String gaptype = s.getPostGapType();
|
||||
DefaultMutableTreeNode prev = s.getPreviousSibling();
|
||||
String prevtype = "sentence";
|
||||
if (prev instanceof Sentence) {
|
||||
Sentence s2 = (Sentence)prev;
|
||||
prevtype = s2.getPostGapType();
|
||||
}
|
||||
|
||||
if (prevtype.equals("continuation")) {
|
||||
ret.setIconTextGap(20);
|
||||
}
|
||||
|
||||
if (gaptype.equals("sentence")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
} else if (gaptype.equals("continuation")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
} else if (gaptype.equals("paragraph")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 7, 0));
|
||||
} else if (gaptype.equals("section")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 15, 0));
|
||||
}
|
||||
|
||||
} else if (value instanceof Chapter) {
|
||||
ret.setIcon(Icons.chapter);
|
||||
} else if (value instanceof Book) {
|
||||
|
||||
@@ -13,13 +13,14 @@ public class CacheManager {
|
||||
if (ob.lockedInCache()) {
|
||||
cache.add(ob);
|
||||
} else {
|
||||
if (ob instanceof Sentence) {
|
||||
Sentence s = (Sentence)ob;
|
||||
}
|
||||
ob.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
cache.add(c);
|
||||
|
||||
System.gc();
|
||||
}
|
||||
|
||||
public static void setCacheSize(int c) {
|
||||
@@ -27,6 +28,9 @@ public class CacheManager {
|
||||
}
|
||||
|
||||
public static void removeFromCache(Cacheable c) {
|
||||
if (c instanceof Sentence) {
|
||||
Sentence s = (Sentence)c;
|
||||
}
|
||||
cache.remove(c);
|
||||
c.clearCache();
|
||||
}
|
||||
|
||||
@@ -232,5 +232,11 @@ public class Chapter extends DefaultMutableTreeNode {
|
||||
return out;
|
||||
}
|
||||
|
||||
public void resetPostGaps() {
|
||||
for (Enumeration s = children(); s.hasMoreElements();) {
|
||||
Sentence snt = (Sentence)s.nextElement();
|
||||
snt.resetPostGap();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
12
src/uk/co/majenko/audiobookrecorder/Debug.java
Normal file
12
src/uk/co/majenko/audiobookrecorder/Debug.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package uk.co.majenko.audiobookrecorder;
|
||||
|
||||
public class Debug {
|
||||
static long timestamp;
|
||||
|
||||
static void debug(String msg) {
|
||||
long now = System.currentTimeMillis();
|
||||
long diff = now - timestamp;
|
||||
timestamp = now;
|
||||
System.err.println(String.format("%8d - %s", diff, msg));
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,8 @@ public class FlashPanel extends JPanel {
|
||||
public void setFlash(boolean f) {
|
||||
flash = f;
|
||||
|
||||
col = true;
|
||||
|
||||
for (Component o : getComponents()) {
|
||||
((JComponent)o).setVisible(!f);
|
||||
}
|
||||
@@ -42,7 +44,7 @@ public class FlashPanel extends JPanel {
|
||||
if (col) {
|
||||
g.setColor(Color.RED);
|
||||
} else {
|
||||
g.setColor(Color.BLACK);
|
||||
g.setColor(Color.GREEN);
|
||||
}
|
||||
Dimension d = getSize();
|
||||
g.fillRect(0, 0, d.width, d.height);
|
||||
|
||||
@@ -33,4 +33,9 @@ public class Icons {
|
||||
static public final ImageIcon dollar = new ImageIcon(Icons.class.getResource("icons/dollar.png"));
|
||||
static public final ImageIcon attention = new ImageIcon(Icons.class.getResource("icons/attention.png"));
|
||||
static public final ImageIcon normalize = new ImageIcon(Icons.class.getResource("icons/normalize.png"));
|
||||
static public final ImageIcon split = new ImageIcon(Icons.class.getResource("icons/split.png"));
|
||||
static public final ImageIcon cut = new ImageIcon(Icons.class.getResource("icons/cut.png"));
|
||||
static public final ImageIcon docut = new ImageIcon(Icons.class.getResource("icons/do-cut.png"));
|
||||
static public final ImageIcon playto = new ImageIcon(Icons.class.getResource("icons/play-to.png"));
|
||||
static public final ImageIcon disable = new ImageIcon(Icons.class.getResource("icons/disable-effects.png"));
|
||||
}
|
||||
|
||||
@@ -14,9 +14,12 @@ public class MainToolBar extends JToolBar {
|
||||
JButtonSpacePlay recordRoomNoise;
|
||||
JButtonSpacePlay playSentence;
|
||||
JButtonSpacePlay playonSentence;
|
||||
JButtonSpacePlay playtoSentence;
|
||||
JButtonSpacePlay stopPlaying;
|
||||
JButtonSpacePlay eq;
|
||||
JToggleButton mic;
|
||||
JToggleButtonSpacePlay mic;
|
||||
|
||||
JToggleButtonSpacePlay disableEffects;
|
||||
|
||||
AudiobookRecorder root;
|
||||
|
||||
@@ -78,6 +81,14 @@ public class MainToolBar extends JToolBar {
|
||||
});
|
||||
add(playonSentence);
|
||||
|
||||
playtoSentence = new JButtonSpacePlay(Icons.playto, "Play sentence to cut", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
root.playToSelectedSentence();
|
||||
}
|
||||
});
|
||||
add(playtoSentence);
|
||||
playtoSentence.setEnabled(false);
|
||||
|
||||
stopPlaying = new JButtonSpacePlay(Icons.stop, "Stop playing", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
root.stopPlaying();
|
||||
@@ -120,8 +131,34 @@ public class MainToolBar extends JToolBar {
|
||||
|
||||
add(mic);
|
||||
|
||||
addSeparator();
|
||||
|
||||
disableEffects = new JToggleButtonSpacePlay(Icons.disable, "Disable effects", new ActionListener() {
|
||||
Color bgCol = null;
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JToggleButton b = (JToggleButton)e.getSource();
|
||||
if (b.isSelected()) {
|
||||
root.setEffectsEnabled(false);
|
||||
bgCol = b.getBackground();
|
||||
b.setBackground(Color.RED);
|
||||
} else {
|
||||
root.setEffectsEnabled(true);
|
||||
if (bgCol != null) {
|
||||
b.setBackground(bgCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add(disableEffects);
|
||||
|
||||
|
||||
|
||||
setFloatable(false);
|
||||
}
|
||||
|
||||
public void enablePlayTo(boolean b) {
|
||||
playtoSentence.setEnabled(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
int endOffset = 0;
|
||||
int crossStartOffset = -1;
|
||||
int crossEndOffset = -1;
|
||||
String postGapType = "none";
|
||||
|
||||
int sampleSize = -1;
|
||||
|
||||
@@ -183,16 +184,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
|
||||
CacheManager.removeFromCache(this);
|
||||
|
||||
audioData = null;
|
||||
processedAudio = null;
|
||||
|
||||
if (!id.equals("room-noise")) {
|
||||
String tm = Options.get("audio.recording.trim");
|
||||
if (tm.equals("peak")) {
|
||||
autoTrimSamplePeak(true);
|
||||
} else if (tm.equals("fft")) {
|
||||
autoTrimSampleFFT(true);
|
||||
}
|
||||
autoTrimSample(true);
|
||||
if (Options.getBoolean("process.sphinx")) {
|
||||
recognise();
|
||||
}
|
||||
@@ -200,6 +193,19 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
|
||||
}
|
||||
|
||||
public void autoTrimSample() {
|
||||
autoTrimSample(false);
|
||||
}
|
||||
|
||||
public void autoTrimSample(boolean useRaw) {
|
||||
String tm = Options.get("audio.recording.trim");
|
||||
if (tm.equals("peak")) {
|
||||
autoTrimSamplePeak(useRaw);
|
||||
} else if (tm.equals("fft")) {
|
||||
autoTrimSampleFFT(useRaw);
|
||||
}
|
||||
}
|
||||
|
||||
public static final int FFTBuckets = 1024;
|
||||
|
||||
public void autoTrimSampleFFT() {
|
||||
@@ -216,7 +222,6 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
samples = getProcessedAudioData();
|
||||
}
|
||||
if (samples == null) {
|
||||
System.err.println("Error: loading data failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -298,7 +303,6 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
updateCrossings(useRaw);
|
||||
intens = null;
|
||||
samples = null;
|
||||
System.gc();
|
||||
|
||||
}
|
||||
|
||||
@@ -711,8 +715,10 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
if (g <= 0.0001d) g = 1.0d;
|
||||
if (g == gain) return;
|
||||
|
||||
if (gain != g) {
|
||||
clearCache();
|
||||
int gint = (int)(g * 100d);
|
||||
int gainint = (int)(gain * 100d);
|
||||
if (gint != gainint) {
|
||||
CacheManager.removeFromCache(this);
|
||||
}
|
||||
gain = g;
|
||||
}
|
||||
@@ -758,7 +764,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
proc.waitFor();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
clearCache();
|
||||
CacheManager.removeFromCache(Sentence.this);
|
||||
AudiobookRecorder.window.updateWaveform();
|
||||
}
|
||||
}
|
||||
@@ -784,7 +790,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
}
|
||||
}
|
||||
if (backupNumber == -1) {
|
||||
System.err.println("Out of backup space!");
|
||||
debug("Out of backup space!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -848,7 +854,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
}
|
||||
}
|
||||
|
||||
clearCache();
|
||||
CacheManager.removeFromCache(Sentence.this);
|
||||
AudiobookRecorder.window.updateWaveform();
|
||||
}
|
||||
}
|
||||
@@ -891,7 +897,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
clearCache();
|
||||
CacheManager.removeFromCache(this);
|
||||
AudiobookRecorder.window.updateWaveform();
|
||||
}
|
||||
|
||||
@@ -899,7 +905,6 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
long len = s.getFrameLength();
|
||||
int frameSize = format.getFrameSize();
|
||||
int chans = format.getChannels();
|
||||
int bytes = frameSize / chans;
|
||||
|
||||
byte[] frame = new byte[frameSize];
|
||||
double[][] samples = new double[(int)len][2];
|
||||
@@ -916,26 +921,163 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
int right = (rh << 8) | rl;
|
||||
if ((left & 0x8000) == 0x8000) left |= 0xFFFF0000;
|
||||
if ((right & 0x8000) == 0x8000) right |= 0xFFFF0000;
|
||||
samples[(int)fno][LEFT] = (double)left / 32768d;
|
||||
samples[(int)fno][RIGHT] = (double)right / 32768d;
|
||||
samples[(int)fno][LEFT] = (double)left / 32767d;
|
||||
samples[(int)fno][RIGHT] = (double)right / 32767d;
|
||||
} else {
|
||||
int l = frame[0] >= 0 ? frame[0] : 256 + frame[0];
|
||||
int h = frame[1] >= 0 ? frame[1] : 256 + frame[1];
|
||||
int mono = (h << 8) | l;
|
||||
if ((mono & 0x8000) == 0x8000) mono |= 0xFFFF0000;
|
||||
samples[(int)fno][LEFT] = (double)mono / 32768d;
|
||||
samples[(int)fno][RIGHT] = (double)mono / 32768d;
|
||||
samples[(int)fno][LEFT] = (double)mono / 32767d;
|
||||
samples[(int)fno][RIGHT] = (double)mono / 32767d;
|
||||
}
|
||||
}
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
public void writeDoubleDataS16LE(double[][] samples, AudioFormat format) throws IOException {
|
||||
int chans = format.getChannels();
|
||||
|
||||
int frames = samples.length;
|
||||
|
||||
byte[] buffer;
|
||||
|
||||
if (chans == 2) {
|
||||
int buflen = frames * 4;
|
||||
buffer = new byte[buflen];
|
||||
|
||||
for (int i = 0; i < frames; i++) {
|
||||
double left = samples[i][LEFT];
|
||||
double right = samples[i][RIGHT];
|
||||
int off = i * 4;
|
||||
left *= 32767d;
|
||||
right *= 32767d;
|
||||
int li = (int)left;
|
||||
int ri = (int)right;
|
||||
|
||||
if (li > 32767) li = 32767;
|
||||
if (li < -32767) li = -32767;
|
||||
if (ri > 32767) ri = 32767;
|
||||
if (ri < -32767) ri = -32767;
|
||||
|
||||
buffer[off + 0] = (byte)(li & 0xFF);
|
||||
buffer[off + 1] = (byte)((li >> 8) & 0xFF);
|
||||
buffer[off + 2] = (byte)(ri & 0xFF);
|
||||
buffer[off + 3] = (byte)((ri >> 8) & 0xFF);
|
||||
}
|
||||
} else {
|
||||
int buflen = frames * 2;
|
||||
buffer = new byte[buflen];
|
||||
|
||||
for (int i = 0; i < frames; i++) {
|
||||
double left = samples[i][LEFT];
|
||||
double right = samples[i][RIGHT];
|
||||
double mono = (left + right) / 2d;
|
||||
int off = i * 2;
|
||||
mono *= 32767d;
|
||||
int mi = (int)mono;
|
||||
|
||||
if (mi > 32767) mi = 32767;
|
||||
if (mi < -32767) mi = -32767;
|
||||
|
||||
buffer[off + 0] = (byte)(mi & 0xFF);
|
||||
buffer[off + 1] = (byte)((mi >> 8) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
backup();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(buffer);
|
||||
AudioInputStream ais = new AudioInputStream(bis, format, frames);
|
||||
File wavFile = getFile();
|
||||
FileOutputStream fos = new FileOutputStream(wavFile);
|
||||
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, fos);
|
||||
fos.close();
|
||||
ais.close();
|
||||
}
|
||||
|
||||
public void writeDoubleDataS24LE(double[][] samples, AudioFormat format) throws IOException {
|
||||
int chans = format.getChannels();
|
||||
|
||||
int frames = samples.length;
|
||||
|
||||
byte[] buffer;
|
||||
|
||||
if (chans == 2) {
|
||||
int buflen = frames * 6;
|
||||
buffer = new byte[buflen];
|
||||
|
||||
for (int i = 0; i < frames; i++) {
|
||||
double left = samples[i][LEFT];
|
||||
double right = samples[i][RIGHT];
|
||||
int off = i * 6;
|
||||
left *= 8388607d;
|
||||
right *= 8388607d;
|
||||
int li = (int)left;
|
||||
int ri = (int)right;
|
||||
|
||||
if (li > 8388607) li = 8388607;
|
||||
if (li < -8388607) li = -8388607;
|
||||
if (ri > 8388607) ri = 8388607;
|
||||
if (ri < -8388607) ri = -8388607;
|
||||
|
||||
buffer[off + 0] = (byte)(li & 0xFF);
|
||||
buffer[off + 1] = (byte)((li >> 8) & 0xFF);
|
||||
buffer[off + 2] = (byte)((li >> 16) & 0xFF);
|
||||
buffer[off + 3] = (byte)(ri & 0xFF);
|
||||
buffer[off + 4] = (byte)((ri >> 8) & 0xFF);
|
||||
buffer[off + 5] = (byte)((ri >> 16) & 0xFF);
|
||||
}
|
||||
} else {
|
||||
int buflen = frames * 3;
|
||||
buffer = new byte[buflen];
|
||||
|
||||
for (int i = 0; i < frames; i++) {
|
||||
double left = samples[i][LEFT];
|
||||
double right = samples[i][RIGHT];
|
||||
double mono = (left + right) / 2d;
|
||||
int off = i * 3;
|
||||
mono *= 8388607d;
|
||||
int mi = (int)mono;
|
||||
|
||||
if (mi > 8388607) mi = 8388607;
|
||||
if (mi < -8388607) mi = -8388607;
|
||||
|
||||
buffer[off + 0] = (byte)(mi & 0xFF);
|
||||
buffer[off + 1] = (byte)((mi >> 8) & 0xFF);
|
||||
buffer[off + 2] = (byte)((mi >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
backup();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(buffer);
|
||||
AudioInputStream ais = new AudioInputStream(bis, format, frames);
|
||||
File wavFile = getFile();
|
||||
FileOutputStream fos = new FileOutputStream(wavFile);
|
||||
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, fos);
|
||||
fos.close();
|
||||
ais.close();
|
||||
}
|
||||
|
||||
public void writeAudioData(double[][] samples) throws IOException {
|
||||
AudioFormat format = getAudioFormat();
|
||||
|
||||
switch (format.getSampleSizeInBits()) {
|
||||
case 16:
|
||||
writeDoubleDataS16LE(samples, format);
|
||||
break;
|
||||
case 24:
|
||||
writeDoubleDataS24LE(samples, format);
|
||||
break;
|
||||
}
|
||||
|
||||
CacheManager.removeFromCache(this);
|
||||
}
|
||||
|
||||
public double[][] getDoubleDataS24LE(AudioInputStream s, AudioFormat format) throws IOException {
|
||||
long len = s.getFrameLength();
|
||||
int frameSize = format.getFrameSize();
|
||||
int chans = format.getChannels();
|
||||
int bytes = frameSize / chans;
|
||||
|
||||
byte[] frame = new byte[frameSize];
|
||||
double[][] samples = new double[(int)len][2];
|
||||
@@ -955,16 +1097,16 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
int right = (rh << 16) | (rm << 8) | rl;
|
||||
if ((left & 0x800000) == 0x800000) left |= 0xFF000000;
|
||||
if ((right & 0x800000) == 0x800000) right |= 0xFF000000;
|
||||
samples[(int)fno][LEFT] = (double)left / 8388608d;
|
||||
samples[(int)fno][RIGHT] = (double)right / 8388608d;
|
||||
samples[(int)fno][LEFT] = (double)left / 8388607d;
|
||||
samples[(int)fno][RIGHT] = (double)right / 8388607d;
|
||||
} else {
|
||||
int l = frame[0] >= 0 ? frame[0] : 256 + frame[0];
|
||||
int m = frame[1] >= 0 ? frame[1] : 256 + frame[1];
|
||||
int h = frame[2] >= 0 ? frame[2] : 256 + frame[2];
|
||||
int mono = (h << 16) | (m << 8) | l;
|
||||
if ((mono & 0x800000) == 0x800000) mono |= 0xFF000000;
|
||||
samples[(int)fno][LEFT] = (double)mono / 8388608d;
|
||||
samples[(int)fno][RIGHT] = (double)mono / 8388608d;
|
||||
samples[(int)fno][LEFT] = (double)mono / 8388607d;
|
||||
samples[(int)fno][RIGHT] = (double)mono / 8388607d;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -979,7 +1121,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
File f = getFile();
|
||||
try {
|
||||
if (!f.exists()) {
|
||||
System.err.println("TODO: Race condition: wav file doesn't exist yet");
|
||||
debug("TODO: Race condition: wav file doesn't exist yet");
|
||||
return;
|
||||
}
|
||||
AudioInputStream s = AudioSystem.getAudioInputStream(f);
|
||||
@@ -1011,8 +1153,14 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
}
|
||||
|
||||
synchronized public double[][] getProcessedAudioData() {
|
||||
return getProcessedAudioData(true);
|
||||
}
|
||||
|
||||
synchronized public double[][] getProcessedAudioData(boolean effectsEnabled) {
|
||||
loadFile();
|
||||
if (processedAudio != null) return processedAudio;
|
||||
if (processedAudio != null) {
|
||||
return processedAudio;
|
||||
}
|
||||
|
||||
if (audioData == null) return null;
|
||||
processedAudio = new double[audioData.length][2];
|
||||
@@ -1026,6 +1174,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
String def = AudiobookRecorder.window.getDefaultEffectsChain();
|
||||
Effect eff = AudiobookRecorder.window.effects.get(def);
|
||||
|
||||
if (effectsEnabled) {
|
||||
if (eff != null) {
|
||||
eff.init(getAudioFormat().getFrameRate());
|
||||
eff.process(processedAudio);
|
||||
@@ -1041,6 +1190,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add final master gain stage
|
||||
for (int i = 0; i < processedAudio.length; i++) {
|
||||
@@ -1048,15 +1199,24 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
processedAudio[i][RIGHT] *= gain;
|
||||
}
|
||||
|
||||
|
||||
return processedAudio;
|
||||
}
|
||||
|
||||
public double[][] getDoubleAudioData() {
|
||||
return getProcessedAudioData();
|
||||
return getDoubleAudioData(true);
|
||||
}
|
||||
|
||||
public double[][] getDoubleAudioData(boolean effectsEnabled) {
|
||||
return getProcessedAudioData(effectsEnabled);
|
||||
}
|
||||
|
||||
public double[][] getCroppedAudioData() {
|
||||
double[][] inSamples = getDoubleAudioData();
|
||||
return getCroppedAudioData(true);
|
||||
}
|
||||
|
||||
public double[][] getCroppedAudioData(boolean effectsEnabled) {
|
||||
double[][] inSamples = getDoubleAudioData(effectsEnabled);
|
||||
if (inSamples == null) return null;
|
||||
updateCrossings();
|
||||
|
||||
@@ -1071,21 +1231,25 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
}
|
||||
|
||||
public byte[] getPCMData() {
|
||||
double[][] croppedData = getCroppedAudioData();
|
||||
return getPCMData(true);
|
||||
}
|
||||
|
||||
public byte[] getPCMData(boolean effectsEnabled) {
|
||||
double[][] croppedData = getCroppedAudioData(effectsEnabled);
|
||||
if (croppedData == null) return null;
|
||||
int length = croppedData.length;
|
||||
byte[] pcmData = new byte[length * 4];
|
||||
for (int i = 0; i < length; i++) {
|
||||
double sd = croppedData[i][LEFT] * 32768d;
|
||||
double sd = croppedData[i][LEFT] * 32767d;
|
||||
int si = (int)sd;
|
||||
if (si > 32767) si = 32767;
|
||||
if (si < -32768) si = -32768;
|
||||
if (si < -32767) si = -32767;
|
||||
pcmData[i * 4] = (byte)(si & 0xFF);
|
||||
pcmData[(i * 4) + 1] = (byte)((si & 0xFF00) >> 8);
|
||||
sd = croppedData[i][RIGHT] * 32768d;
|
||||
sd = croppedData[i][RIGHT] * 32767d;
|
||||
si = (int)sd;
|
||||
if (si > 32767) si = 32767;
|
||||
if (si < -32768) si = -32768;
|
||||
if (si < -32767) si = -32767;
|
||||
pcmData[(i * 4) + 2] = (byte)(si & 0xFF);
|
||||
pcmData[(i * 4) + 3] = (byte)((si & 0xFF00) >> 8);
|
||||
}
|
||||
@@ -1094,7 +1258,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
|
||||
public void setEffectChain(String key) {
|
||||
if ((effectChain != null) && (!effectChain.equals(key))) {
|
||||
clearCache();
|
||||
CacheManager.removeFromCache(this);
|
||||
}
|
||||
effectChain = key;
|
||||
}
|
||||
@@ -1103,4 +1267,45 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
||||
if (effectChain == null) return "none";
|
||||
return effectChain;
|
||||
}
|
||||
|
||||
public String getPostGapType() {
|
||||
return postGapType;
|
||||
}
|
||||
|
||||
public void setPostGapType(String t) {
|
||||
if (t == null || t.equals("none")) {
|
||||
if (getPostGap() == Options.getInteger("catenation.short-sentence")) {
|
||||
t = "continuation";
|
||||
} else if (getPostGap() == Options.getInteger("catenation.post-paragraph")) {
|
||||
t = "paragraph";
|
||||
} else if (getPostGap() == Options.getInteger("catenation.post-section")) {
|
||||
t = "section";
|
||||
} else if (getPostGap() == Options.getInteger("catenation.post-sentence")) {
|
||||
t = "sentence";
|
||||
} else {
|
||||
t = "sentence";
|
||||
}
|
||||
}
|
||||
postGapType = t;
|
||||
}
|
||||
|
||||
public void resetPostGap() {
|
||||
if (postGapType == null) {
|
||||
postGapType = "sentence";
|
||||
}
|
||||
if (postGapType.equals("continuation")) {
|
||||
setPostGap(Options.getInteger("catenation.short-sentence"));
|
||||
} else if (postGapType.equals("paragraph")) {
|
||||
setPostGap(Options.getInteger("catenation.post-paragraph"));
|
||||
} else if (postGapType.equals("section")) {
|
||||
setPostGap(Options.getInteger("catenation.post-section"));
|
||||
} else {
|
||||
setPostGap(Options.getInteger("catenation.post-sentence"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void debug(String txt) {
|
||||
Debug.debug(String.format("%s: %s", id, txt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
int leftAltMarker = 0;
|
||||
int rightAltMarker = 0;
|
||||
|
||||
int cutEntry = 0;
|
||||
int cutExit = 0;
|
||||
boolean displayCut = false;
|
||||
boolean displaySplit = false;
|
||||
|
||||
int dragging = 0;
|
||||
|
||||
int step = 1;
|
||||
@@ -133,7 +138,7 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
g.drawLine(n, (int)(h/2 + lave), n, (int)(h/2 - have));
|
||||
}
|
||||
|
||||
g.setColor(new Color(255, 0, 0, 32));
|
||||
g.setColor(new Color(255, 0, 0, 64));
|
||||
g.fillRect(0, 0, (leftAltMarker - offset)/step, h);
|
||||
g.fillRect((rightAltMarker - offset)/step, 0, (num - rightAltMarker) / step , h);
|
||||
|
||||
@@ -145,6 +150,19 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
g.drawLine((leftMarker - offset)/step, 0, (leftMarker - offset)/step, h);
|
||||
g.drawLine((rightMarker - offset)/step, 0, (rightMarker - offset)/step, h);
|
||||
|
||||
if (displayCut || displaySplit) {
|
||||
g.setColor(new Color(0, 255, 255));
|
||||
g.drawLine((cutEntry - offset)/step, 0, (cutEntry - offset)/step, h);
|
||||
}
|
||||
|
||||
if (displayCut) {
|
||||
g.setColor(new Color(0, 255, 255));
|
||||
g.drawLine((cutExit - offset)/step, 0, (cutExit - offset)/step, h);
|
||||
|
||||
g.setColor(new Color(0, 255, 255, 80));
|
||||
g.fillRect((cutEntry - offset)/step, 0, ((cutExit - offset) - (cutEntry - offset))/step , h);
|
||||
}
|
||||
|
||||
g.setColor(new Color(0, 255, 255));
|
||||
for (int i = 0; i < h; i += 2) {
|
||||
g.drawLine((playMarker - offset) / step, i, (playMarker - offset) / step, i);
|
||||
@@ -192,6 +210,8 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
public void setData(double[][] s) {
|
||||
samples = s;
|
||||
playMarker = 0;
|
||||
displayCut = false;
|
||||
displaySplit = false;
|
||||
repaint();
|
||||
}
|
||||
|
||||
@@ -221,6 +241,19 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
dragging = 2;
|
||||
return;
|
||||
}
|
||||
if (displayCut || displaySplit) {
|
||||
if ((x >= ((cutEntry - offset)/step) - 10) && (x <= ((cutEntry - offset)/step) + 10)) {
|
||||
dragging = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (displayCut) {
|
||||
if ((x >= ((cutExit - offset)/step) - 10) && (x <= ((cutExit - offset)/step) + 10)) {
|
||||
dragging = 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
@@ -251,6 +284,19 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
|
||||
return;
|
||||
}
|
||||
if (displayCut || displaySplit) {
|
||||
if ((x >= ((cutEntry - offset)/step) - 10) && (x <= ((cutEntry - offset)/step) + 10)) {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (displayCut) {
|
||||
if ((x >= ((cutExit - offset)/step) - 10) && (x <= ((cutExit - offset)/step) + 10)) {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
|
||||
@@ -270,6 +316,18 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
if (rightMarker < leftMarker) {
|
||||
rightMarker = leftMarker;
|
||||
}
|
||||
} else if (dragging == 3) {
|
||||
cutEntry = (x * step) + offset;
|
||||
if (displayCut) {
|
||||
if (cutEntry > cutExit) {
|
||||
cutEntry = cutExit;
|
||||
}
|
||||
}
|
||||
} else if (dragging == 4) {
|
||||
cutExit = (x * step) + offset;
|
||||
if (cutExit < cutEntry) {
|
||||
cutExit = cutEntry;
|
||||
}
|
||||
}
|
||||
|
||||
repaint();
|
||||
@@ -299,4 +357,33 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
playMarker = leftAltMarker + m;
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void setDisplayCut(boolean c) {
|
||||
displayCut = c;
|
||||
displaySplit = false;
|
||||
if (displayCut) {
|
||||
int d = rightMarker - leftMarker;
|
||||
cutEntry = leftMarker + (d / 3);
|
||||
cutExit = leftMarker + (d / 3 * 2);
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void setDisplaySplit(boolean c) {
|
||||
displayCut = false;
|
||||
displaySplit = c;
|
||||
if (displaySplit) {
|
||||
int d = rightMarker - leftMarker;
|
||||
cutEntry = leftMarker + (d / 2);
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
public int getCutStart() {
|
||||
return cutEntry;
|
||||
}
|
||||
|
||||
public int getCutEnd() {
|
||||
return cutExit;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user