Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3eb6704f2f | |||
| cd24beb8a6 | |||
| fa287305eb | |||
| 3fb656b693 | |||
| f514993525 | |||
| 81787260c9 | |||
| f9ad396228 | |||
| 8976f2e359 | |||
| 187c3edaf6 | |||
| 02e85fb354 | |||
| 289834021f | |||
| 04fea4acb2 | |||
| 54739b0a75 | |||
| ea5520a729 | |||
| 0a19d8d308 | |||
| 4dbe3e23b7 | |||
| c43cfc3b69 | |||
| babd3d2052 | |||
| 9464839b4d | |||
| bcf7875414 | |||
| 732894a0fb |
@@ -1 +1 @@
|
|||||||
version=0.1.7
|
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() {
|
public FontUIResource getControlTextFont() {
|
||||||
if (controlFont == null) {
|
if (controlFont == null) {
|
||||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||||
controlFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
controlFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||||
} else {
|
} else {
|
||||||
controlFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
controlFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||||
}
|
}
|
||||||
@@ -806,7 +806,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
|||||||
public FontUIResource getSystemTextFont() {
|
public FontUIResource getSystemTextFont() {
|
||||||
if (systemFont == null) {
|
if (systemFont == null) {
|
||||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||||
systemFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
systemFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||||
} else {
|
} else {
|
||||||
systemFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
systemFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||||
}
|
}
|
||||||
@@ -817,7 +817,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
|||||||
public FontUIResource getUserTextFont() {
|
public FontUIResource getUserTextFont() {
|
||||||
if (userFont == null) {
|
if (userFont == null) {
|
||||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||||
userFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
userFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||||
} else {
|
} else {
|
||||||
userFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
userFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||||
}
|
}
|
||||||
@@ -828,7 +828,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
|||||||
public FontUIResource getMenuTextFont() {
|
public FontUIResource getMenuTextFont() {
|
||||||
if (menuFont == null) {
|
if (menuFont == null) {
|
||||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||||
menuFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
menuFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||||
} else {
|
} else {
|
||||||
menuFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
menuFont = new FontUIResource(DIALOG, Font.PLAIN, 12);
|
||||||
}
|
}
|
||||||
@@ -839,9 +839,9 @@ public abstract class AbstractTheme extends MetalTheme {
|
|||||||
public FontUIResource getWindowTitleFont() {
|
public FontUIResource getWindowTitleFont() {
|
||||||
if (windowTitleFont == null) {
|
if (windowTitleFont == null) {
|
||||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||||
windowTitleFont = new FontUIResource(DIALOG, Font.BOLD, 14);
|
windowTitleFont = new FontUIResource(DIALOG, Font.PLAIN, 14); // bold
|
||||||
} else {
|
} else {
|
||||||
windowTitleFont = new FontUIResource(DIALOG, Font.BOLD, 12);
|
windowTitleFont = new FontUIResource(DIALOG, Font.PLAIN, 12); // bold
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return windowTitleFont;
|
return windowTitleFont;
|
||||||
@@ -850,7 +850,7 @@ public abstract class AbstractTheme extends MetalTheme {
|
|||||||
public FontUIResource getSubTextFont() {
|
public FontUIResource getSubTextFont() {
|
||||||
if (smallFont == null) {
|
if (smallFont == null) {
|
||||||
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
if (JTattooUtilities.isLinux() && JTattooUtilities.isHiresScreen()) {
|
||||||
smallFont = new FontUIResource(DIALOG, Font.BOLD, 12);
|
smallFont = new FontUIResource(DIALOG, Font.PLAIN, 12); // bold
|
||||||
} else {
|
} else {
|
||||||
smallFont = new FontUIResource(DIALOG, Font.PLAIN, 10);
|
smallFont = new FontUIResource(DIALOG, Font.PLAIN, 10);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,11 +125,11 @@ public class HiFiDefaultTheme extends AbstractTheme {
|
|||||||
tooltipForegroundColor = white;
|
tooltipForegroundColor = white;
|
||||||
tooltipBackgroundColor = new ColorUIResource(24, 24, 24);
|
tooltipBackgroundColor = new ColorUIResource(24, 24, 24);
|
||||||
|
|
||||||
controlFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
controlFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||||
systemFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
systemFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||||
userFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
userFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||||
menuFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
menuFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||||
windowTitleFont = new FontUIResource("Dialog", Font.BOLD, 12);
|
windowTitleFont = new FontUIResource("Dialog", Font.PLAIN, 12); // bold
|
||||||
smallFont = new FontUIResource("Dialog", Font.PLAIN, 10);
|
smallFont = new FontUIResource("Dialog", Font.PLAIN, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,18 +42,18 @@ public class HiFiLookAndFeel extends AbstractLookAndFeel {
|
|||||||
private static final Properties giantFontProps = new Properties();
|
private static final Properties giantFontProps = new Properties();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
smallFontProps.setProperty("controlTextFont", "Dialog bold 10");
|
smallFontProps.setProperty("controlTextFont", "Dialog 10"); // bold
|
||||||
smallFontProps.setProperty("systemTextFont", "Dialog bold 10");
|
smallFontProps.setProperty("systemTextFont", "Dialog 10"); // bold
|
||||||
smallFontProps.setProperty("userTextFont", "Dialog 10");
|
smallFontProps.setProperty("userTextFont", "Dialog 10");
|
||||||
smallFontProps.setProperty("menuTextFont", "Dialog bold 10");
|
smallFontProps.setProperty("menuTextFont", "Dialog 10"); // bold
|
||||||
smallFontProps.setProperty("windowTitleFont", "Dialog bold 10");
|
smallFontProps.setProperty("windowTitleFont", "Dialog 10"); // bold
|
||||||
smallFontProps.setProperty("subTextFont", "Dialog 8");
|
smallFontProps.setProperty("subTextFont", "Dialog 8");
|
||||||
|
|
||||||
largeFontProps.setProperty("controlTextFont", "Dialog bold 14");
|
largeFontProps.setProperty("controlTextFont", "Dialog 14"); // bold
|
||||||
largeFontProps.setProperty("systemTextFont", "Dialog bold 14");
|
largeFontProps.setProperty("systemTextFont", "Dialog 14"); // bold
|
||||||
largeFontProps.setProperty("userTextFont", "Dialog bold 14");
|
largeFontProps.setProperty("userTextFont", "Dialog 14"); // bold
|
||||||
largeFontProps.setProperty("menuTextFont", "Dialog bold 14");
|
largeFontProps.setProperty("menuTextFont", "Dialog 14"); // bold
|
||||||
largeFontProps.setProperty("windowTitleFont", "Dialog bold 14");
|
largeFontProps.setProperty("windowTitleFont", "Dialog 14"); // bold
|
||||||
largeFontProps.setProperty("subTextFont", "Dialog 12");
|
largeFontProps.setProperty("subTextFont", "Dialog 12");
|
||||||
|
|
||||||
giantFontProps.setProperty("controlTextFont", "Dialog 18");
|
giantFontProps.setProperty("controlTextFont", "Dialog 18");
|
||||||
|
|||||||
@@ -25,31 +25,31 @@ public class AGC implements Effect {
|
|||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
gain = 1d;
|
gain = 1d;
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
double absSampleLeft = Math.abs(samples[i].left) * gain;
|
double absSampleLeft = Math.abs(samples[i][Sentence.LEFT]) * gain;
|
||||||
double absSampleRight = Math.abs(samples[i].right) * gain;
|
double absSampleRight = Math.abs(samples[i][Sentence.RIGHT]) * gain;
|
||||||
|
|
||||||
|
double factor = 0.0d;
|
||||||
|
|
||||||
if (absSampleLeft > ceiling) {
|
if (absSampleLeft > ceiling) {
|
||||||
gain -= attack;
|
factor = -attack;
|
||||||
if (gain < 0) gain = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (absSampleRight > ceiling) {
|
if (absSampleRight > ceiling) {
|
||||||
gain -= attack;
|
factor = -attack;
|
||||||
if (gain < 0) gain = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((absSampleLeft < ceiling) && (absSampleRight < ceiling)) {
|
if ((absSampleLeft < ceiling) && (absSampleRight < ceiling)) {
|
||||||
gain += decay;
|
factor = decay;
|
||||||
if (gain > limit) {
|
|
||||||
gain = limit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
samples[i].left *= gain;
|
gain += factor;
|
||||||
samples[i].right *= gain;
|
if (gain > limit) gain = limit;
|
||||||
|
|
||||||
|
samples[i][Sentence.LEFT] *= gain;
|
||||||
|
samples[i][Sentence.RIGHT] *= gain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ public class Amplifier implements Effect {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
samples[i].left *= gain;
|
samples[i][Sentence.LEFT] *= gain;
|
||||||
samples[i].right *= gain;
|
samples[i][Sentence.RIGHT] *= gain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,13 @@ import edu.cmu.sphinx.api.*;
|
|||||||
import edu.cmu.sphinx.decoder.adaptation.*;
|
import edu.cmu.sphinx.decoder.adaptation.*;
|
||||||
import edu.cmu.sphinx.result.*;
|
import edu.cmu.sphinx.result.*;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
public class AudiobookRecorder extends JFrame {
|
public class AudiobookRecorder extends JFrame {
|
||||||
|
|
||||||
// Settings - tweakable
|
// 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";
|
public static final String SPHINX_MODEL = "resource:/edu/cmu/sphinx/models/en-us/en-us";
|
||||||
|
|
||||||
@@ -38,6 +39,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
String defaultEffectChain = "none";
|
String defaultEffectChain = "none";
|
||||||
|
|
||||||
|
public final static int IDLE = 0;
|
||||||
|
public final static int RECORDING = 1;
|
||||||
|
public final static int STOPPING = 2;
|
||||||
|
public int state = IDLE;
|
||||||
|
|
||||||
MainToolBar toolBar;
|
MainToolBar toolBar;
|
||||||
|
|
||||||
JMenuBar menuBar;
|
JMenuBar menuBar;
|
||||||
@@ -92,10 +98,14 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
JSpinner gainPercent;
|
JSpinner gainPercent;
|
||||||
JCheckBox locked;
|
JCheckBox locked;
|
||||||
JCheckBox attention;
|
JCheckBox attention;
|
||||||
|
JCheckBox rawAudio;
|
||||||
|
|
||||||
JButtonSpacePlay reprocessAudioFFT;
|
JButtonSpacePlay reprocessAudioFFT;
|
||||||
JButtonSpacePlay reprocessAudioPeak;
|
JButtonSpacePlay reprocessAudioPeak;
|
||||||
JButtonSpacePlay normalizeAudio;
|
JButtonSpacePlay normalizeAudio;
|
||||||
|
JToggleButtonSpacePlay selectSplitMode;
|
||||||
|
JToggleButtonSpacePlay selectCutMode;
|
||||||
|
JButtonSpacePlay doCutSplit;
|
||||||
|
|
||||||
JComboBox<KVPair<String,String>> effectChain;
|
JComboBox<KVPair<String,String>> effectChain;
|
||||||
|
|
||||||
@@ -105,6 +115,8 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
SourceDataLine play = null;
|
SourceDataLine play = null;
|
||||||
|
|
||||||
|
boolean effectsEnabled = true;
|
||||||
|
|
||||||
public TargetDataLine microphone = null;
|
public TargetDataLine microphone = null;
|
||||||
public AudioInputStream microphoneStream = null;
|
public AudioInputStream microphoneStream = null;
|
||||||
|
|
||||||
@@ -298,6 +310,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
window = this;
|
window = this;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String clsname = "com.jtattoo.plaf.hifi.HiFiLookAndFeel";
|
String clsname = "com.jtattoo.plaf.hifi.HiFiLookAndFeel";
|
||||||
UIManager.setLookAndFeel(clsname);
|
UIManager.setLookAndFeel(clsname);
|
||||||
|
|
||||||
@@ -312,8 +325,6 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
Method mth = cls.getMethod("setCurrentTheme", cArg);
|
Method mth = cls.getMethod("setCurrentTheme", cArg);
|
||||||
mth.invoke(cls, p);
|
mth.invoke(cls, p);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -386,7 +397,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (selectedSentence != null) {
|
if (selectedSentence != null) {
|
||||||
selectedSentence.autoTrimSampleFFT();
|
selectedSentence.autoTrimSampleFFT();
|
||||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||||
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
||||||
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
||||||
postSentenceGap.setValue(selectedSentence.getPostGap());
|
postSentenceGap.setValue(selectedSentence.getPostGap());
|
||||||
@@ -399,7 +410,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (selectedSentence != null) {
|
if (selectedSentence != null) {
|
||||||
selectedSentence.autoTrimSamplePeak();
|
selectedSentence.autoTrimSamplePeak();
|
||||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||||
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
||||||
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
||||||
postSentenceGap.setValue(selectedSentence.getPostGap());
|
postSentenceGap.setValue(selectedSentence.getPostGap());
|
||||||
@@ -412,11 +423,28 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (selectedSentence != null) {
|
if (selectedSentence != null) {
|
||||||
selectedSentence.normalize();
|
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 = new JSpinner(new SteppedNumericSpinnerModel(0, 5000, 100, 0));
|
||||||
postSentenceGap.setPreferredSize(new Dimension(50, 20));
|
postSentenceGap.setPreferredSize(new Dimension(50, 20));
|
||||||
@@ -438,7 +466,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
JSpinner ob = (JSpinner)e.getSource();
|
JSpinner ob = (JSpinner)e.getSource();
|
||||||
if (selectedSentence != null) {
|
if (selectedSentence != null) {
|
||||||
selectedSentence.setGain((Integer)ob.getValue() / 100d);
|
selectedSentence.setGain((Integer)ob.getValue() / 100d);
|
||||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -457,6 +485,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
controlsLeft.add(reprocessAudioPeak);
|
controlsLeft.add(reprocessAudioPeak);
|
||||||
controlsLeft.add(normalizeAudio);
|
controlsLeft.add(normalizeAudio);
|
||||||
|
|
||||||
|
rawAudio = new JCheckBox("Raw Audio");
|
||||||
|
rawAudio.setFocusable(false);
|
||||||
|
|
||||||
|
controlsTop.add(rawAudio);
|
||||||
|
|
||||||
locked = new JCheckBox("Phrase locked");
|
locked = new JCheckBox("Phrase locked");
|
||||||
locked.setFocusable(false);
|
locked.setFocusable(false);
|
||||||
|
|
||||||
@@ -476,6 +509,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
gainPercent.setEnabled(!selectedSentence.isLocked());
|
gainPercent.setEnabled(!selectedSentence.isLocked());
|
||||||
reprocessAudioFFT.setEnabled(!selectedSentence.isLocked());
|
reprocessAudioFFT.setEnabled(!selectedSentence.isLocked());
|
||||||
reprocessAudioPeak.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);
|
bookTreeModel.reload(selectedSentence);
|
||||||
}
|
}
|
||||||
@@ -549,6 +587,10 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
controlsBottom.add(selectSplitMode);
|
||||||
|
controlsBottom.add(selectCutMode);
|
||||||
|
controlsBottom.add(doCutSplit);
|
||||||
|
|
||||||
sampleControl.add(controlsTop, BorderLayout.NORTH);
|
sampleControl.add(controlsTop, BorderLayout.NORTH);
|
||||||
sampleControl.add(controlsLeft, BorderLayout.WEST);
|
sampleControl.add(controlsLeft, BorderLayout.WEST);
|
||||||
sampleControl.add(controlsRight, BorderLayout.EAST);
|
sampleControl.add(controlsRight, BorderLayout.EAST);
|
||||||
@@ -586,8 +628,13 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
centralPanel.getActionMap().put("startRecord", new AbstractAction() {
|
centralPanel.getActionMap().put("startRecord", new AbstractAction() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (bookTree.isEditing()) return;
|
if (!getLock()) return;
|
||||||
|
if (bookTree.isEditing()) {
|
||||||
|
freeLock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (getNoiseFloor() == 0) {
|
if (getNoiseFloor() == 0) {
|
||||||
|
freeLock();
|
||||||
alertNoRoomNoise();
|
alertNoRoomNoise();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -596,8 +643,13 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
});
|
});
|
||||||
centralPanel.getActionMap().put("startRecordShort", new AbstractAction() {
|
centralPanel.getActionMap().put("startRecordShort", new AbstractAction() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (bookTree.isEditing()) return;
|
if (!getLock()) return;
|
||||||
|
if (bookTree.isEditing()) {
|
||||||
|
freeLock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (getNoiseFloor() == 0) {
|
if (getNoiseFloor() == 0) {
|
||||||
|
freeLock();
|
||||||
alertNoRoomNoise();
|
alertNoRoomNoise();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -606,9 +658,14 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
});
|
});
|
||||||
centralPanel.getActionMap().put("startRecordNewPara", new AbstractAction() {
|
centralPanel.getActionMap().put("startRecordNewPara", new AbstractAction() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (bookTree.isEditing()) return;
|
if (!getLock()) return;
|
||||||
|
if (bookTree.isEditing()) {
|
||||||
|
freeLock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (getNoiseFloor() == 0) {
|
if (getNoiseFloor() == 0) {
|
||||||
alertNoRoomNoise();
|
alertNoRoomNoise();
|
||||||
|
freeLock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startRecordingNewParagraph();
|
startRecordingNewParagraph();
|
||||||
@@ -616,8 +673,13 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
});
|
});
|
||||||
centralPanel.getActionMap().put("startRecordNewSection", new AbstractAction() {
|
centralPanel.getActionMap().put("startRecordNewSection", new AbstractAction() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (bookTree.isEditing()) return;
|
if (!getLock()) return;
|
||||||
|
if (bookTree.isEditing()) {
|
||||||
|
freeLock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (getNoiseFloor() == 0) {
|
if (getNoiseFloor() == 0) {
|
||||||
|
freeLock();
|
||||||
alertNoRoomNoise();
|
alertNoRoomNoise();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -626,8 +688,13 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
});
|
});
|
||||||
centralPanel.getActionMap().put("startRerecord", new AbstractAction() {
|
centralPanel.getActionMap().put("startRerecord", new AbstractAction() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (bookTree.isEditing()) return;
|
if (!getLock()) return;
|
||||||
|
if (bookTree.isEditing()) {
|
||||||
|
freeLock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (getNoiseFloor() == 0) {
|
if (getNoiseFloor() == 0) {
|
||||||
|
freeLock();
|
||||||
alertNoRoomNoise();
|
alertNoRoomNoise();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -637,7 +704,9 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
centralPanel.getActionMap().put("stopRecord", new AbstractAction() {
|
centralPanel.getActionMap().put("stopRecord", new AbstractAction() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (bookTree.isEditing()) return;
|
if (bookTree.isEditing()) return;
|
||||||
|
stopLock();
|
||||||
stopRecording();
|
stopRecording();
|
||||||
|
freeLock();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
centralPanel.getActionMap().put("deleteLast", new AbstractAction() {
|
centralPanel.getActionMap().put("deleteLast", new AbstractAction() {
|
||||||
@@ -916,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() {
|
JMenuObject ins = new JMenuObject("Insert phrase above", s, new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@@ -999,6 +1134,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
menu.add(moveUp);
|
menu.add(moveUp);
|
||||||
menu.add(moveDown);
|
menu.add(moveDown);
|
||||||
menu.add(moveMenu);
|
menu.add(moveMenu);
|
||||||
|
menu.add(setGapType);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.add(edit);
|
menu.add(edit);
|
||||||
menu.add(external);
|
menu.add(external);
|
||||||
@@ -1029,26 +1165,36 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
JMenuObject peak = new JMenuObject("Auto-trim all (Peak)", c, new ActionListener() {
|
JMenuObject peak = new JMenuObject("Auto-trim all (Peak)", c, new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
JMenuObject o = (JMenuObject)e.getSource();
|
JMenuObject o = (JMenuObject)e.getSource();
|
||||||
Chapter c = (Chapter)o.getObject();
|
Chapter chap = (Chapter)o.getObject();
|
||||||
for (Enumeration s = c.children(); s.hasMoreElements();) {
|
|
||||||
Sentence snt = (Sentence)s.nextElement();
|
ProgressDialog ed = new ProgressDialog("Auto-trimming " + chap.getName());
|
||||||
if (!snt.isLocked()) {
|
|
||||||
snt.autoTrimSamplePeak();
|
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() {
|
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) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
JMenuObject o = (JMenuObject)e.getSource();
|
JMenuObject o = (JMenuObject)e.getSource();
|
||||||
Chapter c = (Chapter)o.getObject();
|
Chapter c = (Chapter)o.getObject();
|
||||||
for (Enumeration s = c.children(); s.hasMoreElements();) {
|
c.resetPostGaps();
|
||||||
Sentence snt = (Sentence)s.nextElement();
|
|
||||||
if (!snt.isLocked()) {
|
|
||||||
snt.autoTrimSampleFFT();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1185,12 +1331,16 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
JMenuObject normalizeAll = new JMenuObject("Normalize chapter", c, new ActionListener() {
|
JMenuObject normalizeAll = new JMenuObject("Normalize chapter", c, new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
JMenuObject o = (JMenuObject)e.getSource();
|
JMenuObject o = (JMenuObject)e.getSource();
|
||||||
Chapter c = (Chapter)o.getObject();
|
Chapter chap = (Chapter)o.getObject();
|
||||||
for (Enumeration s = c.children(); s.hasMoreElements();) {
|
|
||||||
Sentence snt = (Sentence)s.nextElement();
|
ProgressDialog ed = new ProgressDialog("Normalizing " + chap.getName());
|
||||||
snt.normalize();
|
|
||||||
}
|
NormalizeThread t = new NormalizeThread(chap, ed);
|
||||||
|
Thread nt = new Thread(t);
|
||||||
|
nt.start();
|
||||||
|
ed.setVisible(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1219,6 +1369,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
menu.add(convertAll);
|
menu.add(convertAll);
|
||||||
menu.add(normalizeAll);
|
menu.add(normalizeAll);
|
||||||
|
menu.add(resetChapterGaps);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.add(moveUp);
|
menu.add(moveUp);
|
||||||
menu.add(moveDown);
|
menu.add(moveDown);
|
||||||
@@ -1307,6 +1458,17 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
});
|
});
|
||||||
menu.add(editData);
|
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());
|
menu.show(bookTree, e.getX(), e.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1384,6 +1546,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (lastLeaf instanceof Sentence) {
|
if (lastLeaf instanceof Sentence) {
|
||||||
Sentence lastSentence = (Sentence)lastLeaf;
|
Sentence lastSentence = (Sentence)lastLeaf;
|
||||||
lastSentence.setPostGap(Options.getInteger("catenation.short-sentence"));
|
lastSentence.setPostGap(Options.getInteger("catenation.short-sentence"));
|
||||||
|
lastSentence.setPostGapType("continuation");
|
||||||
}
|
}
|
||||||
|
|
||||||
Sentence s = new Sentence();
|
Sentence s = new Sentence();
|
||||||
@@ -1434,6 +1597,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (lastLeaf instanceof Sentence) {
|
if (lastLeaf instanceof Sentence) {
|
||||||
Sentence lastSentence = (Sentence)lastLeaf;
|
Sentence lastSentence = (Sentence)lastLeaf;
|
||||||
lastSentence.setPostGap(Options.getInteger("catenation.post-paragraph"));
|
lastSentence.setPostGap(Options.getInteger("catenation.post-paragraph"));
|
||||||
|
lastSentence.setPostGapType("paragraph");
|
||||||
}
|
}
|
||||||
|
|
||||||
Sentence s = new Sentence();
|
Sentence s = new Sentence();
|
||||||
@@ -1483,6 +1647,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (lastLeaf instanceof Sentence) {
|
if (lastLeaf instanceof Sentence) {
|
||||||
Sentence lastSentence = (Sentence)lastLeaf;
|
Sentence lastSentence = (Sentence)lastLeaf;
|
||||||
lastSentence.setPostGap(Options.getInteger("catenation.post-section"));
|
lastSentence.setPostGap(Options.getInteger("catenation.post-section"));
|
||||||
|
lastSentence.setPostGapType("section");
|
||||||
}
|
}
|
||||||
|
|
||||||
Sentence s = new Sentence();
|
Sentence s = new Sentence();
|
||||||
@@ -1532,6 +1697,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (lastLeaf instanceof Sentence) {
|
if (lastLeaf instanceof Sentence) {
|
||||||
Sentence lastSentence = (Sentence)lastLeaf;
|
Sentence lastSentence = (Sentence)lastLeaf;
|
||||||
lastSentence.setPostGap(Options.getInteger("catenation.post-sentence"));
|
lastSentence.setPostGap(Options.getInteger("catenation.post-sentence"));
|
||||||
|
lastSentence.setPostGapType("sentence");
|
||||||
}
|
}
|
||||||
|
|
||||||
Sentence s = new Sentence();
|
Sentence s = new Sentence();
|
||||||
@@ -1657,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.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.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.effect", keybase, i), snt.getEffectChain());
|
||||||
|
prefs.setProperty(String.format("%s.sentence.%08d.gaptype", keybase, i), snt.getPostGapType());
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1665,13 +1832,14 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
try {
|
try {
|
||||||
fos = new FileOutputStream(config);
|
fos = new FileOutputStream(config);
|
||||||
prefs.storeToXML(fos, "Audiobook Recorder Description");
|
prefs.storeToXML(fos, "Audiobook Recorder Description");
|
||||||
} catch (Exception e) {
|
} catch (Exception ex) {
|
||||||
e.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
if (fos != null) {
|
if (fos != null) {
|
||||||
try {
|
try {
|
||||||
fos.close();
|
fos.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1759,7 +1927,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (n instanceof Sentence) {
|
if (n instanceof Sentence) {
|
||||||
Sentence s = (Sentence)n;
|
Sentence s = (Sentence)n;
|
||||||
selectedSentence = s;
|
selectedSentence = s;
|
||||||
sampleWaveform.setData(s.getDoubleAudioData());
|
sampleWaveform.setData(s.getDoubleAudioData(effectsEnabled));
|
||||||
sampleWaveform.setMarkers(s.getStartOffset(), s.getEndOffset());
|
sampleWaveform.setMarkers(s.getStartOffset(), s.getEndOffset());
|
||||||
s.updateCrossings();
|
s.updateCrossings();
|
||||||
sampleWaveform.setAltMarkers(s.getStartCrossing(), s.getEndCrossing());
|
sampleWaveform.setAltMarkers(s.getStartCrossing(), s.getEndCrossing());
|
||||||
@@ -1774,6 +1942,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
gainPercent.setEnabled(!s.isLocked());
|
gainPercent.setEnabled(!s.isLocked());
|
||||||
reprocessAudioFFT.setEnabled(!s.isLocked());
|
reprocessAudioFFT.setEnabled(!s.isLocked());
|
||||||
reprocessAudioPeak.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 {
|
} else {
|
||||||
selectedSentence = null;
|
selectedSentence = null;
|
||||||
sampleWaveform.clearData();
|
sampleWaveform.clearData();
|
||||||
@@ -1781,6 +1954,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
gainPercent.setValue(100);
|
gainPercent.setValue(100);
|
||||||
locked.setSelected(false);
|
locked.setSelected(false);
|
||||||
attention.setSelected(false);
|
attention.setSelected(false);
|
||||||
|
selectCutMode.setEnabled(false);
|
||||||
|
selectSplitMode.setEnabled(false);
|
||||||
|
doCutSplit.setEnabled(false);
|
||||||
|
selectCutMode.setSelected(false);
|
||||||
|
selectSplitMode.setSelected(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1822,6 +2000,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.audition.sentence.%08d.attention", i))));
|
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.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.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());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1843,6 +2022,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.open.sentence.%08d.attention", i))));
|
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.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.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());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1870,6 +2050,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.attention", cno, i))));
|
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.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.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());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1892,6 +2073,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.close.sentence.%08d.attention", i))));
|
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.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.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());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1943,14 +2125,14 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
public double getNoiseFloor() {
|
public double getNoiseFloor() {
|
||||||
if (roomNoise == null) return 0;
|
if (roomNoise == null) return 0;
|
||||||
Sample[] samples = roomNoise.getDoubleAudioData();
|
double[][] samples = roomNoise.getDoubleAudioData();
|
||||||
if (samples == null) {
|
if (samples == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
double ms = 0;
|
double ms = 0;
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
if (Math.abs(samples[i].getMono()) > ms) {
|
if (Math.abs((samples[i][Sentence.LEFT] + samples[i][Sentence.RIGHT]) / 2d) > ms) {
|
||||||
ms = Math.abs(samples[i].getMono());
|
ms = Math.abs((samples[i][Sentence.LEFT] + samples[i][Sentence.RIGHT]) / 2d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2006,9 +2188,10 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
||||||
play.open(format);
|
play.open(format);
|
||||||
play.start();
|
play.start();
|
||||||
|
play.drain();
|
||||||
|
|
||||||
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
|
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
|
||||||
data = s.getPCMData();
|
data = s.getPCMData(effectsEnabled);
|
||||||
for (int pos = 0; pos < data.length; pos += PLAYBACK_CHUNK_SIZE) {
|
for (int pos = 0; pos < data.length; pos += PLAYBACK_CHUNK_SIZE) {
|
||||||
sampleWaveform.setPlayMarker(pos / format.getFrameSize());
|
sampleWaveform.setPlayMarker(pos / format.getFrameSize());
|
||||||
int l = data.length - pos;
|
int l = data.length - pos;
|
||||||
@@ -2029,6 +2212,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
play.close();
|
play.close();
|
||||||
}
|
}
|
||||||
play = null;
|
play = null;
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2037,6 +2221,72 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
playingThread.start();
|
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 {
|
class ExportThread implements Runnable {
|
||||||
ProgressDialog exportDialog;
|
ProgressDialog exportDialog;
|
||||||
Chapter chapter;
|
Chapter chapter;
|
||||||
@@ -2078,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() {
|
public void playFromSelectedSentence() {
|
||||||
if (selectedSentence == null) return;
|
if (selectedSentence == null) return;
|
||||||
if (playing != null) return;
|
if (playing != null) return;
|
||||||
@@ -2099,6 +2425,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
||||||
play.open(format);
|
play.open(format);
|
||||||
play.start();
|
play.start();
|
||||||
|
play.drain();
|
||||||
|
|
||||||
while (playing != null) {
|
while (playing != null) {
|
||||||
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
|
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
|
||||||
@@ -2113,13 +2440,13 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
data = getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter")));
|
data = getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter")));
|
||||||
play.write(data, 0, data.length);
|
play.write(data, 0, data.length);
|
||||||
}
|
}
|
||||||
data = s.getPCMData();
|
data = s.getPCMData(effectsEnabled);
|
||||||
DefaultMutableTreeNode next = s.getNextSibling();
|
DefaultMutableTreeNode next = s.getNextSibling();
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
Thread t = new Thread(new Runnable() {
|
Thread t = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
Sentence ns = (Sentence)next;
|
Sentence ns = (Sentence)next;
|
||||||
ns.getProcessedAudioData(); // Cache it
|
ns.getProcessedAudioData(effectsEnabled); // Cache it
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
t.start();
|
t.start();
|
||||||
@@ -2143,6 +2470,12 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
play.write(data, 0, data.length);
|
play.write(data, 0, data.length);
|
||||||
playing = null;
|
playing = null;
|
||||||
} else {
|
} else {
|
||||||
|
play.drain();
|
||||||
|
play.stop();
|
||||||
|
play.close();
|
||||||
|
play.open(format);
|
||||||
|
play.start();
|
||||||
|
play.drain();
|
||||||
data = getRoomNoise(s.getPostGap());
|
data = getRoomNoise(s.getPostGap());
|
||||||
play.write(data, 0, data.length);
|
play.write(data, 0, data.length);
|
||||||
}
|
}
|
||||||
@@ -2163,6 +2496,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
play.close();
|
play.close();
|
||||||
}
|
}
|
||||||
play = null;
|
play = null;
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2370,6 +2704,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
try {
|
try {
|
||||||
Files.copy(srcFile.toPath(), dstFile.toPath());
|
Files.copy(srcFile.toPath(), dstFile.toPath());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2497,6 +2832,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
f.delete();
|
f.delete();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
pd.closeDialog();
|
pd.closeDialog();
|
||||||
}
|
}
|
||||||
@@ -2644,7 +2980,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
public void updateWaveform() {
|
public void updateWaveform() {
|
||||||
if (selectedSentence != null) {
|
if (selectedSentence != null) {
|
||||||
sampleWaveform.setData(selectedSentence.getDoubleAudioData());
|
if (rawAudio.isSelected()) {
|
||||||
|
sampleWaveform.setData(selectedSentence.getRawAudioData());
|
||||||
|
} else {
|
||||||
|
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2659,6 +2999,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
public void loadEffectsFromFolder(File dir) {
|
public void loadEffectsFromFolder(File dir) {
|
||||||
if (dir == null) return;
|
if (dir == null) return;
|
||||||
|
if (!dir.exists()) return;
|
||||||
File[] files = dir.listFiles();
|
File[] files = dir.listFiles();
|
||||||
for (File f : files) {
|
for (File f : files) {
|
||||||
if (f.getName().endsWith(".eff")) {
|
if (f.getName().endsWith(".eff")) {
|
||||||
@@ -2715,6 +3056,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
group.addEffect(eff);
|
group.addEffect(eff);
|
||||||
}
|
}
|
||||||
|
} else if (e.getTagName().equals("chain")) {
|
||||||
|
Effect eff = (Effect)loadChain(e);
|
||||||
|
if (eff != null) {
|
||||||
|
group.addEffect(eff);
|
||||||
|
}
|
||||||
} else if (e.getTagName().equals("group")) {
|
} else if (e.getTagName().equals("group")) {
|
||||||
Effect eff = (Effect)loadEffectGroup(e);
|
Effect eff = (Effect)loadEffectGroup(e);
|
||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
@@ -2815,6 +3161,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
store.addEffect(eff);
|
store.addEffect(eff);
|
||||||
}
|
}
|
||||||
|
} else if (ie.getTagName().equals("chain")) {
|
||||||
|
Effect eff = (Effect)loadChain(ie);
|
||||||
|
if (eff != null) {
|
||||||
|
store.addEffect(eff);
|
||||||
|
}
|
||||||
} else if (ie.getTagName().equals("group")) {
|
} else if (ie.getTagName().equals("group")) {
|
||||||
Effect eff = (Effect)loadEffectGroup(ie);
|
Effect eff = (Effect)loadEffectGroup(ie);
|
||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
@@ -2850,6 +3201,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Chain loadChain(Element root) {
|
||||||
|
Chain c = new Chain(root.getAttribute("src"));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
public Pan loadPan(Element root) {
|
public Pan loadPan(Element root) {
|
||||||
Pan p = new Pan(Utils.s2d(root.getAttribute("pan")));
|
Pan p = new Pan(Utils.s2d(root.getAttribute("pan")));
|
||||||
return p;
|
return p;
|
||||||
@@ -2925,4 +3281,120 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
public String getDefaultEffectsChain() {
|
public String getDefaultEffectsChain() {
|
||||||
return defaultEffectChain;
|
return defaultEffectChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized boolean getLock() {
|
||||||
|
if (state == RECORDING) return false;
|
||||||
|
|
||||||
|
int counts = 0;
|
||||||
|
while (state == STOPPING) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
counts++;
|
||||||
|
if (counts > 100) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = RECORDING;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void freeLock() {
|
||||||
|
state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopLock() {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,24 +89,24 @@ public class Biquad implements Effect {
|
|||||||
setPeakGain(peakGainDB);
|
setPeakGain(peakGainDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
lz1 = 0d;
|
lz1 = 0d;
|
||||||
lz2 = 0d;
|
lz2 = 0d;
|
||||||
rz1 = 0d;
|
rz1 = 0d;
|
||||||
rz2 = 0d;
|
rz2 = 0d;
|
||||||
for (Sample in : samples) {
|
for (double[] in : samples) {
|
||||||
double lout = in.left * a0 + lz1;
|
double lout = in[Sentence.LEFT] * a0 + lz1;
|
||||||
|
|
||||||
lz1 = in.left * a1 + lz2 - b1 * lout;
|
lz1 = in[Sentence.LEFT] * a1 + lz2 - b1 * lout;
|
||||||
lz2 = in.left * a2 - b2 * lout;
|
lz2 = in[Sentence.LEFT] * a2 - b2 * lout;
|
||||||
|
|
||||||
double rout = in.right * a0 + rz1;
|
double rout = in[Sentence.RIGHT] * a0 + rz1;
|
||||||
|
|
||||||
rz1 = in.right * a1 + rz2 - b1 * rout;
|
rz1 = in[Sentence.RIGHT] * a1 + rz2 - b1 * rout;
|
||||||
rz2 = in.right * a2 - b2 * rout;
|
rz2 = in[Sentence.RIGHT] * a2 - b2 * rout;
|
||||||
|
|
||||||
in.left = lout;
|
in[Sentence.LEFT] = lout;
|
||||||
in.right = rout;
|
in[Sentence.RIGHT] = rout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ package uk.co.majenko.audiobookrecorder;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.tree.*;
|
import javax.swing.tree.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import javax.swing.border.*;
|
||||||
|
|
||||||
public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
||||||
|
|
||||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
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);
|
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) {
|
if (value instanceof Sentence) {
|
||||||
Sentence s = (Sentence)value;
|
Sentence s = (Sentence)value;
|
||||||
|
|
||||||
@@ -39,6 +42,28 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
|||||||
|
|
||||||
ret.setIcon(icn);
|
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) {
|
} else if (value instanceof Chapter) {
|
||||||
ret.setIcon(Icons.chapter);
|
ret.setIcon(Icons.chapter);
|
||||||
} else if (value instanceof Book) {
|
} else if (value instanceof Book) {
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ public class CacheManager {
|
|||||||
if (ob.lockedInCache()) {
|
if (ob.lockedInCache()) {
|
||||||
cache.add(ob);
|
cache.add(ob);
|
||||||
} else {
|
} else {
|
||||||
|
if (ob instanceof Sentence) {
|
||||||
|
Sentence s = (Sentence)ob;
|
||||||
|
}
|
||||||
ob.clearCache();
|
ob.clearCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,4 +26,12 @@ public class CacheManager {
|
|||||||
public static void setCacheSize(int c) {
|
public static void setCacheSize(int c) {
|
||||||
cacheSize = c;
|
cacheSize = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void removeFromCache(Cacheable c) {
|
||||||
|
if (c instanceof Sentence) {
|
||||||
|
Sentence s = (Sentence)c;
|
||||||
|
}
|
||||||
|
cache.remove(c);
|
||||||
|
c.clearCache();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
58
src/uk/co/majenko/audiobookrecorder/Chain.java
Normal file
58
src/uk/co/majenko/audiobookrecorder/Chain.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package uk.co.majenko.audiobookrecorder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Chain implements Effect {
|
||||||
|
String target;
|
||||||
|
|
||||||
|
public Chain(String t) {
|
||||||
|
target = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chain() {
|
||||||
|
target = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process(double[][] samples) {
|
||||||
|
if (target != null) {
|
||||||
|
Effect t = AudiobookRecorder.window.effects.get(target);
|
||||||
|
if (t != null) {
|
||||||
|
t.process(samples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget(String t) {
|
||||||
|
target = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "Chain to " + target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump() {
|
||||||
|
System.out.println(toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(double sf) {
|
||||||
|
if (target != null) {
|
||||||
|
Effect t = AudiobookRecorder.window.effects.get(target);
|
||||||
|
if (t != null) {
|
||||||
|
t.init(sf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Effect> getChildEffects() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -122,7 +122,7 @@ public class Chapter extends DefaultMutableTreeNode {
|
|||||||
|
|
||||||
|
|
||||||
AudioFormat sampleformat = AudiobookRecorder.window.roomNoise.getAudioFormat();
|
AudioFormat sampleformat = AudiobookRecorder.window.roomNoise.getAudioFormat();
|
||||||
AudioFormat format = new AudioFormat(sampleformat.getSampleRate(), 16, 1, true, false);
|
AudioFormat format = new AudioFormat(sampleformat.getSampleRate(), 16, 2, true, false);
|
||||||
byte[] data;
|
byte[] data;
|
||||||
|
|
||||||
int fullLength = 0;
|
int fullLength = 0;
|
||||||
@@ -232,5 +232,11 @@ public class Chapter extends DefaultMutableTreeNode {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resetPostGaps() {
|
||||||
|
for (Enumeration s = children(); s.hasMoreElements();) {
|
||||||
|
Sentence snt = (Sentence)s.nextElement();
|
||||||
|
snt.resetPostGap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ public class Clipping implements Effect {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
for (Sample sample : samples) {
|
for (double[] sample : samples) {
|
||||||
if (sample.left > clip) sample.left = clip;
|
if (sample[Sentence.LEFT] > clip) sample[Sentence.LEFT] = clip;
|
||||||
if (sample.left < -clip) sample.left = -clip;
|
if (sample[Sentence.LEFT] < -clip) sample[Sentence.LEFT] = -clip;
|
||||||
if (sample.right > clip) sample.right = clip;
|
if (sample[Sentence.RIGHT] > clip) sample[Sentence.RIGHT] = clip;
|
||||||
if (sample.right < -clip) sample.right = -clip;
|
if (sample[Sentence.RIGHT] < -clip) sample[Sentence.RIGHT] = -clip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,22 +16,28 @@ public class DelayLine implements Effect {
|
|||||||
return "Delay Line (" + delayLines.size() + " lines)";
|
return "Delay Line (" + delayLines.size() + " lines)";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
Sample[] savedSamples = new Sample[samples.length];
|
double[][] savedSamples = new double[samples.length][2];
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
savedSamples[i] = new Sample(samples[i].left, samples[i].right);
|
savedSamples[i][Sentence.LEFT] = samples[i][Sentence.LEFT];
|
||||||
|
savedSamples[i][Sentence.RIGHT] = samples[i][Sentence.RIGHT];
|
||||||
}
|
}
|
||||||
if (wetOnly) {
|
if (wetOnly) {
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
samples[i].left = 0d;
|
samples[i][Sentence.LEFT] = 0d;
|
||||||
samples[i].right = 0d;
|
samples[i][Sentence.RIGHT] = 0d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double[][] subSamples = new double[samples.length][2];
|
||||||
|
for (int i = 0; i < samples.length; i++) {
|
||||||
|
subSamples[i][Sentence.LEFT] = savedSamples[i][Sentence.LEFT];
|
||||||
|
subSamples[i][Sentence.RIGHT] = savedSamples[i][Sentence.RIGHT];
|
||||||
|
}
|
||||||
for (DelayLineStore d : delayLines) {
|
for (DelayLineStore d : delayLines) {
|
||||||
Sample[] subSamples = new Sample[samples.length];
|
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
subSamples[i] = new Sample(savedSamples[i].left, savedSamples[i].right);
|
subSamples[i][Sentence.LEFT] = savedSamples[i][Sentence.LEFT];
|
||||||
|
subSamples[i][Sentence.RIGHT] = savedSamples[i][Sentence.RIGHT];
|
||||||
}
|
}
|
||||||
|
|
||||||
d.process(subSamples);
|
d.process(subSamples);
|
||||||
@@ -40,31 +46,31 @@ public class DelayLine implements Effect {
|
|||||||
int off = i + d.getSamples();
|
int off = i + d.getSamples();
|
||||||
if ((off < samples.length) && (off > 0)) {
|
if ((off < samples.length) && (off > 0)) {
|
||||||
|
|
||||||
Sample ns = mix(samples[off], subSamples[i]);
|
double[] ns = mix(samples[off], subSamples[i]);
|
||||||
samples[off].left = ns.left;
|
samples[off][Sentence.LEFT] = ns[Sentence.LEFT];
|
||||||
samples[off].right = ns.right;
|
samples[off][Sentence.RIGHT] = ns[Sentence.RIGHT];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sample mix(Sample a, Sample b) {
|
double[] mix(double[] a, double[] b) {
|
||||||
Sample out = new Sample(0, 0);
|
double[] out = new double[2];
|
||||||
|
|
||||||
if ((a.left < 0) && (b.left < 0)) {
|
if ((a[Sentence.LEFT] < 0) && (b[Sentence.LEFT] < 0)) {
|
||||||
out.left = (a.left + b.left) - (a.left * b.left);
|
out[Sentence.LEFT] = (a[Sentence.LEFT] + b[Sentence.LEFT]) - (a[Sentence.LEFT] * b[Sentence.LEFT]);
|
||||||
} else if ((a.left > 0) && (b.left > 0)) {
|
} else if ((a[Sentence.LEFT] > 0) && (b[Sentence.LEFT] > 0)) {
|
||||||
out.left = (a.left + b.left) - (a.left * b.left);
|
out[Sentence.LEFT] = (a[Sentence.LEFT] + b[Sentence.LEFT]) - (a[Sentence.LEFT] * b[Sentence.LEFT]);
|
||||||
} else {
|
} else {
|
||||||
out.left = a.left + b.left;
|
out[Sentence.LEFT] = a[Sentence.LEFT] + b[Sentence.LEFT];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((a.right < 0) && (b.right < 0)) {
|
if ((a[Sentence.RIGHT] < 0) && (b[Sentence.RIGHT] < 0)) {
|
||||||
out.right = (a.right + b.right) - (a.right * b.right);
|
out[Sentence.RIGHT] = (a[Sentence.RIGHT] + b[Sentence.RIGHT]) - (a[Sentence.RIGHT] * b[Sentence.RIGHT]);
|
||||||
} else if ((a.right > 0) && (b.right > 0)) {
|
} else if ((a[Sentence.RIGHT] > 0) && (b[Sentence.RIGHT] > 0)) {
|
||||||
out.right = (a.right + b.right) - (a.right * b.right);
|
out[Sentence.RIGHT] = (a[Sentence.RIGHT] + b[Sentence.RIGHT]) - (a[Sentence.RIGHT] * b[Sentence.RIGHT]);
|
||||||
} else {
|
} else {
|
||||||
out.right = a.right + b.right;
|
out[Sentence.RIGHT] = a[Sentence.RIGHT] + b[Sentence.RIGHT];
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|||||||
@@ -24,21 +24,21 @@ public class DelayLineStore {
|
|||||||
effects = new ArrayList<Effect>();
|
effects = new ArrayList<Effect>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
for (Effect e : effects) {
|
for (Effect e : effects) {
|
||||||
e.process(samples);
|
e.process(samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Sample sample : samples) {
|
for (double[] sample : samples) {
|
||||||
sample.left *= gain;
|
sample[Sentence.LEFT] *= gain;
|
||||||
sample.right *= gain;
|
sample[Sentence.RIGHT] *= gain;
|
||||||
|
|
||||||
if (pan < 0) {
|
if (pan < 0) {
|
||||||
double p = 1 + pan;
|
double p = 1 + pan;
|
||||||
sample.right *= p;
|
sample[Sentence.RIGHT] *= p;
|
||||||
} else {
|
} else {
|
||||||
double p = 1 - pan;
|
double p = 1 - pan;
|
||||||
sample.left *= p;
|
sample[Sentence.LEFT] *= p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package uk.co.majenko.audiobookrecorder;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public interface Effect {
|
public interface Effect {
|
||||||
public void process(Sample[] samples);
|
public void process(double[][] samples);
|
||||||
public String getName();
|
public String getName();
|
||||||
public ArrayList<Effect> getChildEffects();
|
public ArrayList<Effect> getChildEffects();
|
||||||
public void dump();
|
public void dump();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class EffectGroup implements Effect {
|
|||||||
effects = new ArrayList<Effect>();
|
effects = new ArrayList<Effect>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
for (Effect e : effects) {
|
for (Effect e : effects) {
|
||||||
e.process(samples);
|
e.process(samples);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ public class FlashPanel extends JPanel {
|
|||||||
public void setFlash(boolean f) {
|
public void setFlash(boolean f) {
|
||||||
flash = f;
|
flash = f;
|
||||||
|
|
||||||
|
col = true;
|
||||||
|
|
||||||
for (Component o : getComponents()) {
|
for (Component o : getComponents()) {
|
||||||
((JComponent)o).setVisible(!f);
|
((JComponent)o).setVisible(!f);
|
||||||
}
|
}
|
||||||
@@ -42,7 +44,7 @@ public class FlashPanel extends JPanel {
|
|||||||
if (col) {
|
if (col) {
|
||||||
g.setColor(Color.RED);
|
g.setColor(Color.RED);
|
||||||
} else {
|
} else {
|
||||||
g.setColor(Color.BLACK);
|
g.setColor(Color.GREEN);
|
||||||
}
|
}
|
||||||
Dimension d = getSize();
|
Dimension d = getSize();
|
||||||
g.fillRect(0, 0, d.width, d.height);
|
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 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 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 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"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ public class LFO implements Effect {
|
|||||||
phase = p;
|
phase = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
for (Sample sample : samples) {
|
for (double[] sample : samples) {
|
||||||
double v = Math.sin(phase);
|
double v = Math.sin(phase);
|
||||||
phase += sampleStep;
|
phase += sampleStep;
|
||||||
if (phase > (Math.PI * 2d)) {
|
if (phase > (Math.PI * 2d)) {
|
||||||
@@ -38,8 +38,8 @@ public class LFO implements Effect {
|
|||||||
v *= depth;
|
v *= depth;
|
||||||
|
|
||||||
// Apply it to the sample
|
// Apply it to the sample
|
||||||
sample.left += (sample.left * v);
|
sample[Sentence.LEFT] += (sample[Sentence.LEFT] * v);
|
||||||
sample.right += (sample.right * v);
|
sample[Sentence.RIGHT] += (sample[Sentence.RIGHT] * v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,12 @@ public class MainToolBar extends JToolBar {
|
|||||||
JButtonSpacePlay recordRoomNoise;
|
JButtonSpacePlay recordRoomNoise;
|
||||||
JButtonSpacePlay playSentence;
|
JButtonSpacePlay playSentence;
|
||||||
JButtonSpacePlay playonSentence;
|
JButtonSpacePlay playonSentence;
|
||||||
|
JButtonSpacePlay playtoSentence;
|
||||||
JButtonSpacePlay stopPlaying;
|
JButtonSpacePlay stopPlaying;
|
||||||
JButtonSpacePlay eq;
|
JButtonSpacePlay eq;
|
||||||
JToggleButton mic;
|
JToggleButtonSpacePlay mic;
|
||||||
|
|
||||||
|
JToggleButtonSpacePlay disableEffects;
|
||||||
|
|
||||||
AudiobookRecorder root;
|
AudiobookRecorder root;
|
||||||
|
|
||||||
@@ -78,6 +81,14 @@ public class MainToolBar extends JToolBar {
|
|||||||
});
|
});
|
||||||
add(playonSentence);
|
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() {
|
stopPlaying = new JButtonSpacePlay(Icons.stop, "Stop playing", new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
root.stopPlaying();
|
root.stopPlaying();
|
||||||
@@ -120,8 +131,34 @@ public class MainToolBar extends JToolBar {
|
|||||||
|
|
||||||
add(mic);
|
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);
|
setFloatable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void enablePlayTo(boolean b) {
|
||||||
|
playtoSentence.setEnabled(b);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ public class Options extends JDialog {
|
|||||||
|
|
||||||
addSeparator(optionsPanel);
|
addSeparator(optionsPanel);
|
||||||
|
|
||||||
cacheSize = addSpinner(optionsPanel, "Cache size:", 0, 5000, 1, getInteger("cache.size"), "");
|
cacheSize = addSpinner(optionsPanel, "Cache size:", 2, 100, 1, getInteger("cache.size"), "");
|
||||||
|
|
||||||
addSeparator(optionsPanel);
|
addSeparator(optionsPanel);
|
||||||
tabs.add("Options", new JScrollPane(optionsPanel));
|
tabs.add("Options", new JScrollPane(optionsPanel));
|
||||||
@@ -775,9 +775,10 @@ public class Options extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static KVPair[] getTrimMethods() {
|
public static KVPair[] getTrimMethods() {
|
||||||
KVPair[] pairs = new KVPair[2];
|
KVPair[] pairs = new KVPair[3];
|
||||||
pairs[0] = new KVPair<String, String>("peak", "Peak Amplitude");
|
pairs[0] = new KVPair<String, String>("none", "None");
|
||||||
pairs[1] = new KVPair<String, String>("fft", "FFT Analysis");
|
pairs[1] = new KVPair<String, String>("peak", "Peak Amplitude");
|
||||||
|
pairs[2] = new KVPair<String, String>("fft", "FFT Analysis");
|
||||||
return pairs;
|
return pairs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ public class Pan implements Effect {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Sample[] samples) {
|
public void process(double[][] samples) {
|
||||||
for (Sample sample : samples) {
|
for (double[] sample : samples) {
|
||||||
if (pan < 0) {
|
if (pan < 0) {
|
||||||
double p = 1 + pan;
|
double p = 1 + pan;
|
||||||
sample.right *= p;
|
sample[Sentence.RIGHT] *= p;
|
||||||
} else {
|
} else {
|
||||||
double p = 1 - pan;
|
double p = 1 - pan;
|
||||||
sample.left *= p;
|
sample[Sentence.LEFT] *= p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
package uk.co.majenko.audiobookrecorder;
|
|
||||||
|
|
||||||
public class Sample {
|
|
||||||
public double left;
|
|
||||||
public double right;
|
|
||||||
|
|
||||||
public Sample(double m) {
|
|
||||||
left = m;
|
|
||||||
right = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Sample(double l, double r) {
|
|
||||||
left = l;
|
|
||||||
right = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getLeft() {
|
|
||||||
return left;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getRight() {
|
|
||||||
return right;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getMono() {
|
|
||||||
return (left + right) / 2.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -39,6 +39,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
int endOffset = 0;
|
int endOffset = 0;
|
||||||
int crossStartOffset = -1;
|
int crossStartOffset = -1;
|
||||||
int crossEndOffset = -1;
|
int crossEndOffset = -1;
|
||||||
|
String postGapType = "none";
|
||||||
|
|
||||||
int sampleSize = -1;
|
int sampleSize = -1;
|
||||||
|
|
||||||
@@ -58,14 +59,18 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public void setOverrideText(String s) { overrideText = s; }
|
public void setOverrideText(String s) { overrideText = s; }
|
||||||
public String getOverrideText() { return overrideText; }
|
public String getOverrideText() { return overrideText; }
|
||||||
|
|
||||||
|
public static final int LEFT = 0;
|
||||||
|
public static final int RIGHT = 1;
|
||||||
|
|
||||||
TargetDataLine line;
|
TargetDataLine line;
|
||||||
AudioInputStream inputStream;
|
AudioInputStream inputStream;
|
||||||
AudioFormat storedFormat = null;
|
AudioFormat storedFormat = null;
|
||||||
double storedLength = -1d;
|
double storedLength = -1d;
|
||||||
|
|
||||||
Sample[] audioData = null;
|
double[][] audioData = null;
|
||||||
Sample[] processedAudio = null;
|
|
||||||
|
double[][] processedAudio = null;
|
||||||
|
|
||||||
RecordingThread recordingThread;
|
RecordingThread recordingThread;
|
||||||
|
|
||||||
boolean effectEthereal = false;
|
boolean effectEthereal = false;
|
||||||
@@ -90,7 +95,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
try {
|
try {
|
||||||
running = true;
|
running = true;
|
||||||
recording = true;
|
recording = true;
|
||||||
byte[] buf = new byte[AudiobookRecorder.window.microphone.getBufferSize()];
|
byte[] buf = new byte[1024]; //AudiobookRecorder.window.microphone.getBufferSize()];
|
||||||
FileOutputStream fos = new FileOutputStream(tempFile);
|
FileOutputStream fos = new FileOutputStream(tempFile);
|
||||||
int len = 0;
|
int len = 0;
|
||||||
AudiobookRecorder.window.microphone.flush();
|
AudiobookRecorder.window.microphone.flush();
|
||||||
@@ -134,7 +139,6 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Sentence() {
|
public Sentence() {
|
||||||
super("");
|
super("");
|
||||||
id = UUID.randomUUID().toString();
|
id = UUID.randomUUID().toString();
|
||||||
@@ -157,6 +161,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CacheManager.removeFromCache(this);
|
||||||
|
|
||||||
recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat());
|
recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat());
|
||||||
|
|
||||||
@@ -173,63 +178,53 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
audioData = null;
|
CacheManager.removeFromCache(this);
|
||||||
storedFormat = null;
|
|
||||||
storedLength = -1;
|
|
||||||
|
|
||||||
if (!id.equals("room-noise")) {
|
if (!id.equals("room-noise")) {
|
||||||
String tm = Options.get("audio.recording.trim");
|
autoTrimSample(true);
|
||||||
if (tm.equals("peak")) {
|
|
||||||
autoTrimSamplePeak();
|
|
||||||
} else if (tm.equals("fft")) {
|
|
||||||
autoTrimSampleFFT();
|
|
||||||
}
|
|
||||||
if (Options.getBoolean("process.sphinx")) {
|
if (Options.getBoolean("process.sphinx")) {
|
||||||
recognise();
|
recognise();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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 static final int FFTBuckets = 1024;
|
||||||
|
|
||||||
public double[][] getFFTProfile() {
|
public void autoTrimSampleFFT() {
|
||||||
double[] real = new double[FFTBuckets];
|
autoTrimSampleFFT(false);
|
||||||
double[] imag = new double[FFTBuckets];
|
|
||||||
|
|
||||||
Sample[] samples = getProcessedAudioData();
|
|
||||||
int slices = (samples.length / FFTBuckets) + 1;
|
|
||||||
|
|
||||||
double[][] out = new double[slices][];
|
|
||||||
|
|
||||||
int slice = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < samples.length; i += FFTBuckets) {
|
|
||||||
for (int j = 0; j < FFTBuckets; j++) {
|
|
||||||
if (i + j < samples.length) {
|
|
||||||
real[j] = samples[i+j].getMono();
|
|
||||||
imag[j] = 0;
|
|
||||||
} else {
|
|
||||||
real[j] = 0;
|
|
||||||
imag[j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out[slice++] = FFT.fft(real, imag, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void autoTrimSampleFFT() {
|
public void autoTrimSampleFFT(boolean useRaw) {
|
||||||
crossStartOffset = -1;
|
crossStartOffset = -1;
|
||||||
crossEndOffset = -1;
|
crossEndOffset = -1;
|
||||||
Sample[] samples = getProcessedAudioData();
|
double[][] samples;
|
||||||
if (samples == null) return;
|
if (useRaw) {
|
||||||
|
samples = getRawAudioData();
|
||||||
|
} else {
|
||||||
|
samples = getProcessedAudioData();
|
||||||
|
}
|
||||||
|
if (samples == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int blocks = samples.length / 4096 + 1;
|
int blocks = samples.length / 4096 + 1;
|
||||||
|
|
||||||
@@ -242,7 +237,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
for (int j = 0; j < 4096; j++) {
|
for (int j = 0; j < 4096; j++) {
|
||||||
if (i + j < samples.length) {
|
if (i + j < samples.length) {
|
||||||
real[j] = samples[i+j].getMono();
|
real[j] = (samples[i+j][LEFT] + samples[i+j][RIGHT]) / 2d;
|
||||||
imag[j] = 0;
|
imag[j] = 0;
|
||||||
} else {
|
} else {
|
||||||
real[j] = 0;
|
real[j] = 0;
|
||||||
@@ -268,6 +263,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
block++;
|
block++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int limit = Options.getInteger("audio.recording.trim.fft");
|
int limit = Options.getInteger("audio.recording.trim.fft");
|
||||||
|
|
||||||
// Find first block with > 1 intensity and subtract one.
|
// Find first block with > 1 intensity and subtract one.
|
||||||
@@ -304,14 +300,25 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
if (endOffset <= startOffset) endOffset = startOffset + 4096;
|
if (endOffset <= startOffset) endOffset = startOffset + 4096;
|
||||||
if (endOffset < 0) endOffset = 0;
|
if (endOffset < 0) endOffset = 0;
|
||||||
if (endOffset >= samples.length) endOffset = samples.length;
|
if (endOffset >= samples.length) endOffset = samples.length;
|
||||||
updateCrossings();
|
updateCrossings(useRaw);
|
||||||
|
intens = null;
|
||||||
|
samples = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void autoTrimSamplePeak() {
|
public void autoTrimSamplePeak() {
|
||||||
|
autoTrimSamplePeak(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void autoTrimSamplePeak(boolean useRaw) {
|
||||||
crossStartOffset = -1;
|
crossStartOffset = -1;
|
||||||
crossEndOffset = -1;
|
crossEndOffset = -1;
|
||||||
Sample[] samples = getProcessedAudioData();
|
double[][] samples;
|
||||||
|
if (useRaw) {
|
||||||
|
samples = getRawAudioData();
|
||||||
|
} else {
|
||||||
|
samples = getProcessedAudioData();
|
||||||
|
}
|
||||||
if (samples == null) return;
|
if (samples == null) return;
|
||||||
double noiseFloor = AudiobookRecorder.window.getNoiseFloor();
|
double noiseFloor = AudiobookRecorder.window.getNoiseFloor();
|
||||||
noiseFloor *= 1.1;
|
noiseFloor *= 1.1;
|
||||||
@@ -319,7 +326,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
// Find start
|
// Find start
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
startOffset = i;
|
startOffset = i;
|
||||||
if (Math.abs(samples[i].getMono()) > noiseFloor) {
|
if (Math.abs((samples[i][LEFT] + samples[i][RIGHT])/2d) > noiseFloor) {
|
||||||
startOffset --;
|
startOffset --;
|
||||||
if (startOffset < 0) startOffset = 0;
|
if (startOffset < 0) startOffset = 0;
|
||||||
break;
|
break;
|
||||||
@@ -334,7 +341,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
for (int i = samples.length-1; i >= 0; i--) {
|
for (int i = samples.length-1; i >= 0; i--) {
|
||||||
endOffset = i;
|
endOffset = i;
|
||||||
if (Math.abs(samples[i].getMono()) > noiseFloor) {
|
if (Math.abs((samples[i][LEFT] + samples[i][RIGHT])/2d) > noiseFloor) {
|
||||||
endOffset ++;
|
endOffset ++;
|
||||||
if (endOffset >= samples.length-1) endOffset = samples.length-1;
|
if (endOffset >= samples.length-1) endOffset = samples.length-1;
|
||||||
break;
|
break;
|
||||||
@@ -350,7 +357,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
if (startOffset < 0) startOffset = 0;
|
if (startOffset < 0) startOffset = 0;
|
||||||
if (endOffset >= samples.length) endOffset = samples.length-1;
|
if (endOffset >= samples.length) endOffset = samples.length-1;
|
||||||
updateCrossings();
|
updateCrossings(useRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@@ -434,19 +441,31 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateCrossings() {
|
public void updateCrossings() {
|
||||||
updateStartCrossing();
|
updateCrossings(false);
|
||||||
updateEndCrossing();
|
}
|
||||||
|
|
||||||
|
public void updateCrossings(boolean useRaw) {
|
||||||
|
updateStartCrossing(useRaw);
|
||||||
|
updateEndCrossing(useRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateStartCrossing() {
|
public void updateStartCrossing() {
|
||||||
|
updateStartCrossing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateStartCrossing(boolean useRaw) {
|
||||||
if (crossStartOffset == -1) {
|
if (crossStartOffset == -1) {
|
||||||
crossStartOffset = findNearestZeroCrossing(startOffset, 4096);
|
crossStartOffset = findNearestZeroCrossing(useRaw, startOffset, 4096);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateEndCrossing() {
|
public void updateEndCrossing() {
|
||||||
|
updateEndCrossing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateEndCrossing(boolean useRaw) {
|
||||||
if (crossEndOffset == -1) {
|
if (crossEndOffset == -1) {
|
||||||
crossEndOffset = findNearestZeroCrossing(endOffset, 4096);
|
crossEndOffset = findNearestZeroCrossing(useRaw, endOffset, 4096);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,6 +585,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
audioData = null;
|
audioData = null;
|
||||||
processedAudio = null;
|
processedAudio = null;
|
||||||
|
storedFormat = null;
|
||||||
|
storedLength = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean lockedInCache() {
|
public boolean lockedInCache() {
|
||||||
@@ -573,7 +594,16 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int findNearestZeroCrossing(int pos, int range) {
|
public int findNearestZeroCrossing(int pos, int range) {
|
||||||
Sample[] data = getProcessedAudioData();
|
return findNearestZeroCrossing(false, pos, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int findNearestZeroCrossing(boolean useRaw, int pos, int range) {
|
||||||
|
double[][] data = null;
|
||||||
|
if (useRaw) {
|
||||||
|
data = getRawAudioData();
|
||||||
|
} else {
|
||||||
|
data = getProcessedAudioData();
|
||||||
|
}
|
||||||
if (data == null) return 0;
|
if (data == null) return 0;
|
||||||
if (data.length == 0) return 0;
|
if (data.length == 0) return 0;
|
||||||
|
|
||||||
@@ -583,19 +613,19 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
int backwards = pos;
|
int backwards = pos;
|
||||||
int forwards = pos;
|
int forwards = pos;
|
||||||
|
|
||||||
double backwardsPrev = data[backwards].getMono();
|
double backwardsPrev = (data[backwards][LEFT] + data[backwards][RIGHT]) / 2d;
|
||||||
double forwardsPrev = data[forwards].getMono();
|
double forwardsPrev = (data[forwards][LEFT] + data[forwards][RIGHT]) / 2d;
|
||||||
|
|
||||||
while (backwards > 0 || forwards < data.length-2) {
|
while (backwards > 0 || forwards < data.length-2) {
|
||||||
|
|
||||||
if (forwards < data.length-2) forwards++;
|
if (forwards < data.length-2) forwards++;
|
||||||
if (backwards > 0) backwards--;
|
if (backwards > 0) backwards--;
|
||||||
|
|
||||||
if (backwardsPrev >= 0 && data[backwards].getMono() < 0) { // Found one!
|
if (backwardsPrev >= 0 && ((data[backwards][LEFT] + data[backwards][RIGHT]) / 2d) < 0) { // Found one!
|
||||||
return backwards;
|
return backwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forwardsPrev < 0 && data[forwards].getMono() >= 0) {
|
if (forwardsPrev < 0 && ((data[forwards][LEFT] + data[forwards][RIGHT]) / 2d) >= 0) {
|
||||||
return forwards;
|
return forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,8 +634,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
backwardsPrev = data[backwards].getMono();
|
backwardsPrev = (data[backwards][LEFT] + data[backwards][RIGHT]) / 2d;
|
||||||
forwardsPrev = data[forwards].getMono();
|
forwardsPrev = (data[forwards][LEFT] + data[forwards][RIGHT]) / 2d;
|
||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
@@ -647,17 +677,26 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public double getPeakValue() {
|
public double getPeakValue() {
|
||||||
|
return getPeakValue(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPeakValue(boolean useRaw) {
|
||||||
double oldGain = gain;
|
double oldGain = gain;
|
||||||
gain = 1.0d;
|
gain = 1.0d;
|
||||||
Sample[] samples = getProcessedAudioData();
|
double[][] samples = null;
|
||||||
|
if (useRaw) {
|
||||||
|
samples = getRawAudioData();
|
||||||
|
} else {
|
||||||
|
samples = getProcessedAudioData();
|
||||||
|
}
|
||||||
gain = oldGain;
|
gain = oldGain;
|
||||||
if (samples == null) {
|
if (samples == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
double ms = 0;
|
double ms = 0;
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
if (Math.abs(samples[i].getMono()) > ms) {
|
if (Math.abs((samples[i][LEFT] + samples[i][RIGHT]) / 2d) > ms) {
|
||||||
ms = Math.abs(samples[i].getMono());
|
ms = Math.abs((samples[i][LEFT] + samples[i][RIGHT]) / 2d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ms;
|
return ms;
|
||||||
@@ -676,8 +715,10 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
if (g <= 0.0001d) g = 1.0d;
|
if (g <= 0.0001d) g = 1.0d;
|
||||||
if (g == gain) return;
|
if (g == gain) return;
|
||||||
|
|
||||||
if (gain != g) {
|
int gint = (int)(g * 100d);
|
||||||
clearCache();
|
int gainint = (int)(gain * 100d);
|
||||||
|
if (gint != gainint) {
|
||||||
|
CacheManager.removeFromCache(this);
|
||||||
}
|
}
|
||||||
gain = g;
|
gain = g;
|
||||||
}
|
}
|
||||||
@@ -723,7 +764,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
proc.waitFor();
|
proc.waitFor();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
clearCache();
|
CacheManager.removeFromCache(Sentence.this);
|
||||||
AudiobookRecorder.window.updateWaveform();
|
AudiobookRecorder.window.updateWaveform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -749,7 +790,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (backupNumber == -1) {
|
if (backupNumber == -1) {
|
||||||
System.err.println("Out of backup space!");
|
debug("Out of backup space!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,7 +854,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCache();
|
CacheManager.removeFromCache(Sentence.this);
|
||||||
AudiobookRecorder.window.updateWaveform();
|
AudiobookRecorder.window.updateWaveform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -856,18 +897,17 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCache();
|
CacheManager.removeFromCache(this);
|
||||||
AudiobookRecorder.window.updateWaveform();
|
AudiobookRecorder.window.updateWaveform();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sample[] getDoubleDataS16LE(AudioInputStream s, AudioFormat format) throws IOException {
|
public double[][] getDoubleDataS16LE(AudioInputStream s, AudioFormat format) throws IOException {
|
||||||
long len = s.getFrameLength();
|
long len = s.getFrameLength();
|
||||||
int frameSize = format.getFrameSize();
|
int frameSize = format.getFrameSize();
|
||||||
int chans = format.getChannels();
|
int chans = format.getChannels();
|
||||||
int bytes = frameSize / chans;
|
|
||||||
|
|
||||||
byte[] frame = new byte[frameSize];
|
byte[] frame = new byte[frameSize];
|
||||||
Sample[] samples = new Sample[(int)len];
|
double[][] samples = new double[(int)len][2];
|
||||||
|
|
||||||
for (long fno = 0; fno < len; fno++) {
|
for (long fno = 0; fno < len; fno++) {
|
||||||
|
|
||||||
@@ -881,27 +921,166 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
int right = (rh << 8) | rl;
|
int right = (rh << 8) | rl;
|
||||||
if ((left & 0x8000) == 0x8000) left |= 0xFFFF0000;
|
if ((left & 0x8000) == 0x8000) left |= 0xFFFF0000;
|
||||||
if ((right & 0x8000) == 0x8000) right |= 0xFFFF0000;
|
if ((right & 0x8000) == 0x8000) right |= 0xFFFF0000;
|
||||||
samples[(int)fno] = new Sample((double)left / 32768d, (double)right / 32768d);
|
samples[(int)fno][LEFT] = (double)left / 32767d;
|
||||||
|
samples[(int)fno][RIGHT] = (double)right / 32767d;
|
||||||
} else {
|
} else {
|
||||||
int l = frame[0] >= 0 ? frame[0] : 256 + frame[0];
|
int l = frame[0] >= 0 ? frame[0] : 256 + frame[0];
|
||||||
int h = frame[1] >= 0 ? frame[1] : 256 + frame[1];
|
int h = frame[1] >= 0 ? frame[1] : 256 + frame[1];
|
||||||
int mono = (h << 8) | l;
|
int mono = (h << 8) | l;
|
||||||
if ((mono & 0x8000) == 0x8000) mono |= 0xFFFF0000;
|
if ((mono & 0x8000) == 0x8000) mono |= 0xFFFF0000;
|
||||||
samples[(int)fno] = new Sample((double)mono / 32768d);
|
samples[(int)fno][LEFT] = (double)mono / 32767d;
|
||||||
|
samples[(int)fno][RIGHT] = (double)mono / 32767d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sample[] getDoubleDataS24LE(AudioInputStream s, AudioFormat format) throws IOException {
|
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();
|
long len = s.getFrameLength();
|
||||||
int frameSize = format.getFrameSize();
|
int frameSize = format.getFrameSize();
|
||||||
int chans = format.getChannels();
|
int chans = format.getChannels();
|
||||||
int bytes = frameSize / chans;
|
|
||||||
|
|
||||||
byte[] frame = new byte[frameSize];
|
byte[] frame = new byte[frameSize];
|
||||||
Sample[] samples = new Sample[(int)len];
|
double[][] samples = new double[(int)len][2];
|
||||||
|
|
||||||
for (long fno = 0; fno < len; fno++) {
|
for (long fno = 0; fno < len; fno++) {
|
||||||
|
|
||||||
@@ -918,14 +1097,16 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
int right = (rh << 16) | (rm << 8) | rl;
|
int right = (rh << 16) | (rm << 8) | rl;
|
||||||
if ((left & 0x800000) == 0x800000) left |= 0xFF000000;
|
if ((left & 0x800000) == 0x800000) left |= 0xFF000000;
|
||||||
if ((right & 0x800000) == 0x800000) right |= 0xFF000000;
|
if ((right & 0x800000) == 0x800000) right |= 0xFF000000;
|
||||||
samples[(int)fno] = new Sample((double)left / 8388608d, (double)right / 8388608d);
|
samples[(int)fno][LEFT] = (double)left / 8388607d;
|
||||||
|
samples[(int)fno][RIGHT] = (double)right / 8388607d;
|
||||||
} else {
|
} else {
|
||||||
int l = frame[0] >= 0 ? frame[0] : 256 + frame[0];
|
int l = frame[0] >= 0 ? frame[0] : 256 + frame[0];
|
||||||
int m = frame[1] >= 0 ? frame[1] : 256 + frame[1];
|
int m = frame[1] >= 0 ? frame[1] : 256 + frame[1];
|
||||||
int h = frame[2] >= 0 ? frame[2] : 256 + frame[2];
|
int h = frame[2] >= 0 ? frame[2] : 256 + frame[2];
|
||||||
int mono = (h << 16) | (m << 8) | l;
|
int mono = (h << 16) | (m << 8) | l;
|
||||||
if ((mono & 0x800000) == 0x800000) mono |= 0xFF000000;
|
if ((mono & 0x800000) == 0x800000) mono |= 0xFF000000;
|
||||||
samples[(int)fno] = new Sample((double)mono / 8388608d);
|
samples[(int)fno][LEFT] = (double)mono / 8388607d;
|
||||||
|
samples[(int)fno][RIGHT] = (double)mono / 8388607d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,14 +1114,20 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadFile() {
|
public void loadFile() {
|
||||||
if (audioData != null) return;
|
if (audioData != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
File f = getFile();
|
File f = getFile();
|
||||||
try {
|
try {
|
||||||
|
if (!f.exists()) {
|
||||||
|
debug("TODO: Race condition: wav file doesn't exist yet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
AudioInputStream s = AudioSystem.getAudioInputStream(f);
|
AudioInputStream s = AudioSystem.getAudioInputStream(f);
|
||||||
AudioFormat format = getAudioFormat();
|
AudioFormat format = getAudioFormat();
|
||||||
|
|
||||||
Sample[] samples = null;
|
double[][] samples = null;
|
||||||
|
|
||||||
switch (format.getSampleSizeInBits()) {
|
switch (format.getSampleSizeInBits()) {
|
||||||
case 16:
|
case 16:
|
||||||
@@ -956,17 +1143,30 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
audioData = samples;
|
audioData = samples;
|
||||||
CacheManager.addToCache(this);
|
CacheManager.addToCache(this);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sample[] getProcessedAudioData() {
|
synchronized public double[][] getRawAudioData() {
|
||||||
loadFile();
|
loadFile();
|
||||||
if (processedAudio != null) return processedAudio;
|
return audioData;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public double[][] getProcessedAudioData() {
|
||||||
|
return getProcessedAudioData(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public double[][] getProcessedAudioData(boolean effectsEnabled) {
|
||||||
|
loadFile();
|
||||||
|
if (processedAudio != null) {
|
||||||
|
return processedAudio;
|
||||||
|
}
|
||||||
|
|
||||||
if (audioData == null) return null;
|
if (audioData == null) return null;
|
||||||
processedAudio = new Sample[audioData.length];
|
processedAudio = new double[audioData.length][2];
|
||||||
for (int i = 0; i < audioData.length; i++) {
|
for (int i = 0; i < audioData.length; i++) {
|
||||||
processedAudio[i] = new Sample(audioData[i].left, audioData[i].right);
|
processedAudio[i][LEFT] = audioData[i][LEFT];
|
||||||
|
processedAudio[i][RIGHT] = audioData[i][RIGHT];
|
||||||
}
|
}
|
||||||
// Add processing in here.
|
// Add processing in here.
|
||||||
|
|
||||||
@@ -974,64 +1174,82 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
String def = AudiobookRecorder.window.getDefaultEffectsChain();
|
String def = AudiobookRecorder.window.getDefaultEffectsChain();
|
||||||
Effect eff = AudiobookRecorder.window.effects.get(def);
|
Effect eff = AudiobookRecorder.window.effects.get(def);
|
||||||
|
|
||||||
if (eff != null) {
|
if (effectsEnabled) {
|
||||||
eff.init(getAudioFormat().getFrameRate());
|
if (eff != null) {
|
||||||
eff.process(processedAudio);
|
eff.init(getAudioFormat().getFrameRate());
|
||||||
}
|
eff.process(processedAudio);
|
||||||
|
}
|
||||||
|
|
||||||
if (effectChain != null) {
|
if (effectChain != null) {
|
||||||
// Don't double up the default chain
|
// Don't double up the default chain
|
||||||
if (!effectChain.equals(def)) {
|
if (!effectChain.equals(def)) {
|
||||||
eff = AudiobookRecorder.window.effects.get(effectChain);
|
eff = AudiobookRecorder.window.effects.get(effectChain);
|
||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
eff.init(getAudioFormat().getFrameRate());
|
eff.init(getAudioFormat().getFrameRate());
|
||||||
eff.process(processedAudio);
|
eff.process(processedAudio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add final master gain stage
|
// Add final master gain stage
|
||||||
for (int i = 0; i < processedAudio.length; i++) {
|
for (int i = 0; i < processedAudio.length; i++) {
|
||||||
processedAudio[i].left = processedAudio[i].left * gain;
|
processedAudio[i][LEFT] *= gain;
|
||||||
processedAudio[i].right = processedAudio[i].right * gain;
|
processedAudio[i][RIGHT] *= gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return processedAudio;
|
return processedAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sample[] getDoubleAudioData() {
|
public double[][] getDoubleAudioData() {
|
||||||
return getProcessedAudioData();
|
return getDoubleAudioData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sample[] getCroppedAudioData() {
|
public double[][] getDoubleAudioData(boolean effectsEnabled) {
|
||||||
Sample[] inSamples = getDoubleAudioData();
|
return getProcessedAudioData(effectsEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][] getCroppedAudioData() {
|
||||||
|
return getCroppedAudioData(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][] getCroppedAudioData(boolean effectsEnabled) {
|
||||||
|
double[][] inSamples = getDoubleAudioData(effectsEnabled);
|
||||||
if (inSamples == null) return null;
|
if (inSamples == null) return null;
|
||||||
updateCrossings();
|
updateCrossings();
|
||||||
|
|
||||||
int length = crossEndOffset - crossStartOffset;
|
int length = crossEndOffset - crossStartOffset;
|
||||||
|
|
||||||
Sample[] samples = new Sample[length];
|
double[][] samples = new double[length][2];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
samples[i] = inSamples[crossStartOffset + i];
|
samples[i][LEFT] = inSamples[crossStartOffset + i][LEFT];
|
||||||
|
samples[i][RIGHT] = inSamples[crossStartOffset + i][RIGHT];
|
||||||
}
|
}
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getPCMData() {
|
public byte[] getPCMData() {
|
||||||
Sample[] croppedData = getCroppedAudioData();
|
return getPCMData(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getPCMData(boolean effectsEnabled) {
|
||||||
|
double[][] croppedData = getCroppedAudioData(effectsEnabled);
|
||||||
if (croppedData == null) return null;
|
if (croppedData == null) return null;
|
||||||
int length = croppedData.length;
|
int length = croppedData.length;
|
||||||
byte[] pcmData = new byte[length * 4];
|
byte[] pcmData = new byte[length * 4];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
double sd = croppedData[i].left * 32768d;
|
double sd = croppedData[i][LEFT] * 32767d;
|
||||||
int si = (int)sd;
|
int si = (int)sd;
|
||||||
if (si > 32767) si = 32767;
|
if (si > 32767) si = 32767;
|
||||||
if (si < -32768) si = -32768;
|
if (si < -32767) si = -32767;
|
||||||
pcmData[i * 4] = (byte)(si & 0xFF);
|
pcmData[i * 4] = (byte)(si & 0xFF);
|
||||||
pcmData[(i * 4) + 1] = (byte)((si & 0xFF00) >> 8);
|
pcmData[(i * 4) + 1] = (byte)((si & 0xFF00) >> 8);
|
||||||
sd = croppedData[i].right * 32768d;
|
sd = croppedData[i][RIGHT] * 32767d;
|
||||||
si = (int)sd;
|
si = (int)sd;
|
||||||
if (si > 32767) si = 32767;
|
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) + 2] = (byte)(si & 0xFF);
|
||||||
pcmData[(i * 4) + 3] = (byte)((si & 0xFF00) >> 8);
|
pcmData[(i * 4) + 3] = (byte)((si & 0xFF00) >> 8);
|
||||||
}
|
}
|
||||||
@@ -1040,7 +1258,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
public void setEffectChain(String key) {
|
public void setEffectChain(String key) {
|
||||||
if ((effectChain != null) && (!effectChain.equals(key))) {
|
if ((effectChain != null) && (!effectChain.equals(key))) {
|
||||||
clearCache();
|
CacheManager.removeFromCache(this);
|
||||||
}
|
}
|
||||||
effectChain = key;
|
effectChain = key;
|
||||||
}
|
}
|
||||||
@@ -1049,4 +1267,45 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
if (effectChain == null) return "none";
|
if (effectChain == null) return "none";
|
||||||
return effectChain;
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,4 +63,17 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long millis = System.currentTimeMillis();
|
||||||
|
|
||||||
|
public static void report(String tag) {
|
||||||
|
long t = System.currentTimeMillis();
|
||||||
|
long d = t - millis;
|
||||||
|
millis = t;
|
||||||
|
System.err.println(String.format("%10d - %10s : %8d | %8d | %8d", d, tag,
|
||||||
|
Runtime.getRuntime().totalMemory(),
|
||||||
|
Runtime.getRuntime().maxMemory(),
|
||||||
|
Runtime.getRuntime().freeMemory()
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import javax.sound.sampled.*;
|
|||||||
|
|
||||||
public class Waveform extends JPanel implements MouseListener, MouseMotionListener {
|
public class Waveform extends JPanel implements MouseListener, MouseMotionListener {
|
||||||
|
|
||||||
Sample[] samples = null;
|
double[][] samples = null;
|
||||||
|
|
||||||
int leftMarker = 0;
|
int leftMarker = 0;
|
||||||
int rightMarker = 0;
|
int rightMarker = 0;
|
||||||
@@ -21,6 +21,11 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
|||||||
int leftAltMarker = 0;
|
int leftAltMarker = 0;
|
||||||
int rightAltMarker = 0;
|
int rightAltMarker = 0;
|
||||||
|
|
||||||
|
int cutEntry = 0;
|
||||||
|
int cutExit = 0;
|
||||||
|
boolean displayCut = false;
|
||||||
|
boolean displaySplit = false;
|
||||||
|
|
||||||
int dragging = 0;
|
int dragging = 0;
|
||||||
|
|
||||||
int step = 1;
|
int step = 1;
|
||||||
@@ -92,7 +97,7 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
|||||||
double lmax = 0;
|
double lmax = 0;
|
||||||
|
|
||||||
for (int o = 0; o < step; o++) {
|
for (int o = 0; o < step; o++) {
|
||||||
double sample = samples[offset + (n * step) + o].getMono();
|
double sample = (samples[offset + (n * step) + o][Sentence.LEFT] + samples[offset + (n * step) + o][Sentence.RIGHT]) / 2d;
|
||||||
if (sample >= 0) {
|
if (sample >= 0) {
|
||||||
have += sample;
|
have += sample;
|
||||||
hcnt++;
|
hcnt++;
|
||||||
@@ -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.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(0, 0, (leftAltMarker - offset)/step, h);
|
||||||
g.fillRect((rightAltMarker - offset)/step, 0, (num - rightAltMarker) / 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((leftMarker - offset)/step, 0, (leftMarker - offset)/step, h);
|
||||||
g.drawLine((rightMarker - offset)/step, 0, (rightMarker - 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));
|
g.setColor(new Color(0, 255, 255));
|
||||||
for (int i = 0; i < h; i += 2) {
|
for (int i = 0; i < h; i += 2) {
|
||||||
g.drawLine((playMarker - offset) / step, i, (playMarker - offset) / step, i);
|
g.drawLine((playMarker - offset) / step, i, (playMarker - offset) / step, i);
|
||||||
@@ -189,9 +207,11 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
|||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(Sample[] s) {
|
public void setData(double[][] s) {
|
||||||
samples = s;
|
samples = s;
|
||||||
playMarker = 0;
|
playMarker = 0;
|
||||||
|
displayCut = false;
|
||||||
|
displaySplit = false;
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +241,19 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
|||||||
dragging = 2;
|
dragging = 2;
|
||||||
return;
|
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) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
@@ -251,6 +284,19 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
|||||||
setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
|
setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
|
||||||
return;
|
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));
|
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
|
|
||||||
@@ -270,6 +316,18 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
|||||||
if (rightMarker < leftMarker) {
|
if (rightMarker < leftMarker) {
|
||||||
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();
|
repaint();
|
||||||
@@ -299,4 +357,33 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
|||||||
playMarker = leftAltMarker + m;
|
playMarker = leftAltMarker + m;
|
||||||
repaint();
|
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