Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 28257e00c0 | |||
| 38c6af7090 | |||
| bdbf4c604d | |||
| 73bcba2c9a | |||
| 90ca84cfbf | |||
| a18ca1ce21 | |||
| b92babb5cd | |||
| e3231ec495 | |||
| 4896ee7a65 | |||
| ce3eb7165a | |||
| 4de00b8fac | |||
| ebe777bdc5 | |||
| 3b5cacb8ad | |||
| db7d297dbc | |||
| 2f9abf7629 | |||
| b6063d2fed | |||
| e1f566f0c8 | |||
| 9fa892a6fd | |||
| 1572e163ef | |||
| 2791691057 | |||
| 575537ae66 | |||
| fde4a597c7 | |||
| e69ae52f50 | |||
| 8bdb06749f | |||
| 0cfd066f4f | |||
| 217ccb915a | |||
| 1dd3e9d86f | |||
| d3d81d71fe | |||
| 80c110afa9 | |||
| 1c08b9a51d | |||
| 4ad30106b6 | |||
| 9100d0e35a | |||
| b8dea19c30 | |||
| 671f2b9270 | |||
| d619fb2f4d |
@@ -1,7 +1,4 @@
|
||||
<effect name="Alien">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<biquad type="lowpass" fc="10000" q="1" gain="-10" />
|
||||
<lfo frequency="100" depth="0.5" />
|
||||
<!--biquad type="lowpass" fc="10000" q="1" gain="-10" /-->
|
||||
<lfo frequency="50" depth="1.0" waveform="triangle" mode="replace"/>
|
||||
</effect>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<effect name="Big Echo">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<delayline>
|
||||
<delay samples="22000" gain="0.2" pan="-0.3">
|
||||
<biquad type="highpass" fc="300" q="1" gain="0" />
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<biquad type="lowpass" fc="10000" q="1" gain="-10" />
|
||||
<agc ceiling="0.666" limit="1" attack="0.1" decay="0.01" />
|
||||
<agc ceiling="0.666" limit="1.5" attack="0.08" decay="0.01" />
|
||||
</effect>
|
||||
|
||||
15
ExampleFilters/cuthumagcstereo.eff
Normal file
15
ExampleFilters/cuthumagcstereo.eff
Normal file
@@ -0,0 +1,15 @@
|
||||
<effect name="Cut Computer Hum (with AGC and Stereo)">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<biquad type="lowpass" fc="10000" q="1" gain="-10" />
|
||||
<delayline wetonly="false">
|
||||
<delay samples="-100" gain="0.1" pan="-1.0">
|
||||
<biquad type="highpass" fc="300" q="1" gain="0" />
|
||||
</delay>
|
||||
<delay samples="100" gain="0.1" pan="1.0">
|
||||
<biquad type="highpass" fc="300" q="1" gain="0" />
|
||||
</delay>
|
||||
</delayline>
|
||||
<agc ceiling="0.666" limit="1.5" attack="0.1" decay="0.01" />
|
||||
</effect>
|
||||
@@ -1,7 +1,4 @@
|
||||
<effect name="Ethereal Voice">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<amplifier gain="0.1" />
|
||||
<delayline>
|
||||
<delay samples="2000" gain="1.0" pan="-0.3">
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<effect name="Large Room (quiet)">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<biquad type="lowpass" fc="10000" q="1" gain="-10" />
|
||||
<delayline>
|
||||
<delay samples="5500" gain="0.2" pan="-0.3">
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<effect name="Large Room (loud)">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<biquad type="lowpass" fc="10000" q="1" gain="-10" />
|
||||
<delayline>
|
||||
<delay samples="5500" gain="0.2" pan="-0.3">
|
||||
|
||||
3
ExampleFilters/panleft.eff
Normal file
3
ExampleFilters/panleft.eff
Normal file
@@ -0,0 +1,3 @@
|
||||
<effect name="Pan Left">
|
||||
<pan pan="-0.4" />
|
||||
</effect>
|
||||
3
ExampleFilters/panright.eff
Normal file
3
ExampleFilters/panright.eff
Normal file
@@ -0,0 +1,3 @@
|
||||
<effect name="Pan Right">
|
||||
<pan pan="0.4" />
|
||||
</effect>
|
||||
@@ -1,7 +1,4 @@
|
||||
<effect name="Telephone">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<biquad type="lowshelf" fc="400" q="10" gain="-20" />
|
||||
<biquad type="highshelf" fc="8000" q="10" gain="-20" />
|
||||
<delayline>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
<effect name="Radio">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<amplifier gain="0.1" />
|
||||
<biquad type="peak" fc="1000" q="10" gain="45" />
|
||||
<lfo frequency="5000" depth="0.3" />
|
||||
<clipping clip="0.3" />
|
||||
<amplifier gain="0.5" />
|
||||
<biquad type="peak" fc="1000" q="10" gain="25" />
|
||||
<lfo frequency="3000" depth="0.3" waveform="sine" mode="add" />
|
||||
<clipping clip="0.9" />
|
||||
<biquad type="highshelf" fc="8000" q="1" gain="-20" />
|
||||
<delayline>
|
||||
<delay samples="100" gain="0.7" />
|
||||
<delay samples="200" gain="0.5" />
|
||||
</delayline>
|
||||
<amplifier gain="0.3" />
|
||||
</effect>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<effect name="Robotic">
|
||||
<biquad type="notch" fc="28" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="91" q="20" gain="-50" />
|
||||
<biquad type="notch" fc="120" q="20" gain="-50" />
|
||||
<biquad type="lowshelf" fc="100" q="2" gain="-20" />
|
||||
<delayline>
|
||||
<delay samples="400" gain="1" pan="-0.3" />
|
||||
|
||||
10
ExampleFilters/stereochorus.eff
Normal file
10
ExampleFilters/stereochorus.eff
Normal file
@@ -0,0 +1,10 @@
|
||||
<effect name="Stereo Chorus">
|
||||
<delayline>
|
||||
<delay samples="2000" gain="0.1" pan="-0.3">
|
||||
<biquad type="highpass" fc="300" q="1" gain="0" />
|
||||
</delay>
|
||||
<delay samples="4000" gain="0.1" pan="0.3">
|
||||
<biquad type="highpass" fc="300" q="1" gain="0" />
|
||||
</delay>
|
||||
</delayline>
|
||||
</effect>
|
||||
@@ -1 +1 @@
|
||||
version=0.2.0
|
||||
version=0.3.5
|
||||
|
||||
BIN
resources/uk/co/majenko/audiobookrecorder/icons/manuscript.png
Normal file
BIN
resources/uk/co/majenko/audiobookrecorder/icons/manuscript.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
@@ -27,9 +27,9 @@ public class AGC implements Effect {
|
||||
|
||||
public void process(double[][] samples) {
|
||||
gain = 1d;
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
double absSampleLeft = Math.abs(samples[i][Sentence.LEFT]) * gain;
|
||||
double absSampleRight = Math.abs(samples[i][Sentence.RIGHT]) * gain;
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
double absSampleLeft = Math.abs(samples[Sentence.LEFT][i]) * gain;
|
||||
double absSampleRight = Math.abs(samples[Sentence.RIGHT][i]) * gain;
|
||||
|
||||
double factor = 0.0d;
|
||||
|
||||
@@ -47,9 +47,10 @@ public class AGC implements Effect {
|
||||
|
||||
gain += factor;
|
||||
if (gain > limit) gain = limit;
|
||||
if (gain < 0) gain = 0;
|
||||
|
||||
samples[i][Sentence.LEFT] *= gain;
|
||||
samples[i][Sentence.RIGHT] *= gain;
|
||||
samples[Sentence.LEFT][i] *= gain;
|
||||
samples[Sentence.RIGHT][i] *= gain;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ public class Amplifier implements Effect {
|
||||
}
|
||||
|
||||
public void process(double[][] samples) {
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
samples[i][Sentence.LEFT] *= gain;
|
||||
samples[i][Sentence.RIGHT] *= gain;
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
samples[Sentence.LEFT][i] *= gain;
|
||||
samples[Sentence.RIGHT][i] *= gain;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -94,19 +94,19 @@ public class Biquad implements Effect {
|
||||
lz2 = 0d;
|
||||
rz1 = 0d;
|
||||
rz2 = 0d;
|
||||
for (double[] in : samples) {
|
||||
double lout = in[Sentence.LEFT] * a0 + lz1;
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
double lout = samples[Sentence.LEFT][i] * a0 + lz1;
|
||||
|
||||
lz1 = in[Sentence.LEFT] * a1 + lz2 - b1 * lout;
|
||||
lz2 = in[Sentence.LEFT] * a2 - b2 * lout;
|
||||
lz1 = samples[Sentence.LEFT][i] * a1 + lz2 - b1 * lout;
|
||||
lz2 = samples[Sentence.LEFT][i] * a2 - b2 * lout;
|
||||
|
||||
double rout = in[Sentence.RIGHT] * a0 + rz1;
|
||||
double rout = samples[Sentence.RIGHT][i] * a0 + rz1;
|
||||
|
||||
rz1 = in[Sentence.RIGHT] * a1 + rz2 - b1 * rout;
|
||||
rz2 = in[Sentence.RIGHT] * a2 - b2 * rout;
|
||||
rz1 = samples[Sentence.RIGHT][i] * a1 + rz2 - b1 * rout;
|
||||
rz2 = samples[Sentence.RIGHT][i] * a2 - b2 * rout;
|
||||
|
||||
in[Sentence.LEFT] = lout;
|
||||
in[Sentence.RIGHT] = rout;
|
||||
samples[Sentence.LEFT][i] = lout;
|
||||
samples[Sentence.RIGHT][i] = rout;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,20 @@ import java.nio.file.*;
|
||||
import javax.swing.tree.*;
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
public class Book extends DefaultMutableTreeNode {
|
||||
|
||||
String name;
|
||||
@@ -17,6 +31,9 @@ public class Book extends DefaultMutableTreeNode {
|
||||
String genre;
|
||||
String comment;
|
||||
String ACX;
|
||||
String manuscript;
|
||||
|
||||
String defaultEffect = "none";
|
||||
|
||||
int sampleRate;
|
||||
int channels;
|
||||
@@ -31,7 +48,64 @@ public class Book extends DefaultMutableTreeNode {
|
||||
|
||||
prefs = p;
|
||||
name = bookname;
|
||||
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name);
|
||||
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
|
||||
}
|
||||
|
||||
public Book(Element root) {
|
||||
super(getTextNode(root, "title"));
|
||||
|
||||
name = getTextNode(root, "title");
|
||||
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
|
||||
}
|
||||
|
||||
public void loadBookXML(Element root, DefaultTreeModel model) {
|
||||
name = getTextNode(root, "title");
|
||||
author = getTextNode(root, "author");
|
||||
genre = getTextNode(root, "genre");
|
||||
comment = getTextNode(root, "comment");
|
||||
ACX = getTextNode(root, "acx");
|
||||
manuscript = getTextNode(root, "manuscript");
|
||||
|
||||
AudiobookRecorder.window.setBookNotes(getTextNode(root, "notes"));
|
||||
|
||||
Element settings = getNode(root, "settings");
|
||||
Element audioSettings = getNode(settings, "audio");
|
||||
Element effectSettings = getNode(settings, "effects");
|
||||
|
||||
sampleRate = Utils.s2i(getTextNode(audioSettings, "samplerate"));
|
||||
channels = Utils.s2i(getTextNode(audioSettings, "channels"));
|
||||
resolution = Utils.s2i(getTextNode(audioSettings, "resolution"));
|
||||
|
||||
defaultEffect = getTextNode(settings, "default");
|
||||
|
||||
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
|
||||
|
||||
Element chapters = getNode(root, "chapters");
|
||||
|
||||
NodeList chapterList = chapters.getElementsByTagName("chapter");
|
||||
|
||||
for (int i = 0; i < chapterList.getLength(); i++) {
|
||||
Element chapterElement = (Element)chapterList.item(i);
|
||||
Chapter newChapter = new Chapter(chapterElement, model);
|
||||
model.insertNodeInto(newChapter, this, getChildCount());
|
||||
}
|
||||
}
|
||||
|
||||
public static Element getNode(Element r, String n) {
|
||||
NodeList nl = r.getElementsByTagName(n);
|
||||
if (nl == null) return null;
|
||||
if (nl.getLength() == 0) return null;
|
||||
return (Element)nl.item(0);
|
||||
}
|
||||
|
||||
public static String getTextNode(Element r, String n) {
|
||||
return getTextNode(r, n, "");
|
||||
}
|
||||
|
||||
public static String getTextNode(Element r, String n, String d) {
|
||||
Element node = getNode(r, n);
|
||||
if (node == null) return d;
|
||||
return node.getTextContent();
|
||||
}
|
||||
|
||||
public void setAuthor(String a) { author = a; }
|
||||
@@ -115,8 +189,12 @@ public class Book extends DefaultMutableTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
public File getBookPath() {
|
||||
return new File(Options.get("path.storage"), name);
|
||||
}
|
||||
|
||||
public void renameBook(String newName) {
|
||||
File oldDir = new File(Options.get("path.storage"), name);
|
||||
File oldDir = getBookPath();
|
||||
File newDir = new File(Options.get("path.storage"), newName);
|
||||
|
||||
if (newDir.exists()) {
|
||||
@@ -206,4 +284,118 @@ public class Book extends DefaultMutableTreeNode {
|
||||
return out;
|
||||
}
|
||||
|
||||
public void purgeBackups() {
|
||||
for (Enumeration o = children(); o.hasMoreElements();) {
|
||||
Object ob = (Object)o.nextElement();
|
||||
if (ob instanceof Chapter) {
|
||||
Chapter c = (Chapter)ob;
|
||||
c.purgeBackups();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Document buildDocument() throws ParserConfigurationException {
|
||||
DocumentBuilderFactory dbFactory =
|
||||
DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.newDocument();
|
||||
|
||||
Element root = doc.createElement("book");
|
||||
doc.appendChild(root);
|
||||
|
||||
root.appendChild(makeTextNode(doc, "title", name));
|
||||
root.appendChild(makeTextNode(doc, "author", author));
|
||||
root.appendChild(makeTextNode(doc, "comment", comment));
|
||||
root.appendChild(makeTextNode(doc, "genre", genre));
|
||||
root.appendChild(makeTextNode(doc, "acx", ACX));
|
||||
root.appendChild(makeTextNode(doc, "manuscript", manuscript));
|
||||
|
||||
root.appendChild(makeTextNode(doc, "notes", AudiobookRecorder.window.getBookNotes()));
|
||||
|
||||
Element settingsNode = doc.createElement("settings");
|
||||
root.appendChild(settingsNode);
|
||||
|
||||
Element audioSettingsNode = doc.createElement("audio");
|
||||
settingsNode.appendChild(audioSettingsNode);
|
||||
|
||||
audioSettingsNode.appendChild(makeTextNode(doc, "channels", channels));
|
||||
audioSettingsNode.appendChild(makeTextNode(doc, "resolution", resolution));
|
||||
audioSettingsNode.appendChild(makeTextNode(doc, "samplerate", sampleRate));
|
||||
|
||||
Element effectsNode = doc.createElement("effects");
|
||||
settingsNode.appendChild(effectsNode);
|
||||
|
||||
effectsNode.appendChild(makeTextNode(doc, "default", defaultEffect));
|
||||
|
||||
Element chaptersNode = doc.createElement("chapters");
|
||||
|
||||
root.appendChild(chaptersNode);
|
||||
|
||||
for (Enumeration o = children(); o.hasMoreElements();) {
|
||||
Object ob = (Object)o.nextElement();
|
||||
if (ob instanceof Chapter) {
|
||||
Chapter c = (Chapter)ob;
|
||||
chaptersNode.appendChild(c.getChapterXML(doc));
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
public static Element makeTextNode(Document doc, String name, String text) {
|
||||
Element node = doc.createElement(name);
|
||||
Text tnode = doc.createTextNode(text == null ? "" : text);
|
||||
node.appendChild(tnode);
|
||||
return node;
|
||||
}
|
||||
|
||||
public static Element makeTextNode(Document doc, String name, Integer text) {
|
||||
Element node = doc.createElement(name);
|
||||
Text tnode = doc.createTextNode(Integer.toString(text));
|
||||
node.appendChild(tnode);
|
||||
return node;
|
||||
}
|
||||
|
||||
public static Element makeTextNode(Document doc, String name, Double text) {
|
||||
Element node = doc.createElement(name);
|
||||
Text tnode = doc.createTextNode(String.format("%.8f", text));
|
||||
node.appendChild(tnode);
|
||||
return node;
|
||||
}
|
||||
|
||||
public static Element makeTextNode(Document doc, String name, Boolean text) {
|
||||
Element node = doc.createElement(name);
|
||||
Text tnode = doc.createTextNode(text ? "true" : "false");
|
||||
node.appendChild(tnode);
|
||||
return node;
|
||||
}
|
||||
|
||||
public String getDefaultEffect() {
|
||||
return defaultEffect;
|
||||
}
|
||||
|
||||
public void setDefaultEffect(String eff) {
|
||||
defaultEffect = eff;
|
||||
}
|
||||
|
||||
public void setManuscript(File f) {
|
||||
manuscript = f.getName();
|
||||
File dst = new File(getBookPath(), manuscript);
|
||||
|
||||
try {
|
||||
Files.copy(f.toPath(), dst.toPath());
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public File getManuscript() {
|
||||
if (manuscript == null) return null;
|
||||
if (manuscript.equals("")) return null;
|
||||
File f = new File(getBookPath(), manuscript);
|
||||
if (f.exists()) {
|
||||
return f;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,20 @@ import javax.swing.border.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
public class BookPanel extends JPanel {
|
||||
String name;
|
||||
String author;
|
||||
@@ -25,6 +39,7 @@ public class BookPanel extends JPanel {
|
||||
JPanel panel;
|
||||
|
||||
File root;
|
||||
File configFile;
|
||||
|
||||
boolean highlight = false;
|
||||
|
||||
@@ -36,13 +51,78 @@ public class BookPanel extends JPanel {
|
||||
try {
|
||||
root = r;
|
||||
Properties props = new Properties();
|
||||
props.loadFromXML(new FileInputStream(new File(root, "audiobook.abk")));
|
||||
loadBookData(props, null);
|
||||
|
||||
configFile = new File(root, "audiobook.abx");
|
||||
|
||||
if (configFile.exists()) {
|
||||
loadXMLData(configFile);
|
||||
} else {
|
||||
configFile = new File(root, "audiobook.abk");
|
||||
props.loadFromXML(new FileInputStream(configFile));
|
||||
loadBookData(props, null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public BookPanel(String n, String a, String g, String c, ImageIcon i) {
|
||||
name = n;
|
||||
author = a;
|
||||
genre = g;
|
||||
comment = c;
|
||||
cover = i;
|
||||
if (i != null) {
|
||||
cover = i;
|
||||
resizedCover = Utils.getScaledImage(cover.getImage(), 75, 75);
|
||||
iconLabel = new JLabel(new ImageIcon(resizedCover));
|
||||
} else {
|
||||
cover = null;
|
||||
resizedCover = null;
|
||||
iconLabel = new JLabel("");
|
||||
}
|
||||
populate();
|
||||
}
|
||||
|
||||
public void loadXMLData(File inputFile) {
|
||||
try {
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.parse(inputFile);
|
||||
doc.getDocumentElement().normalize();
|
||||
|
||||
Element rootnode = doc.getDocumentElement();
|
||||
|
||||
name = Book.getTextNode(rootnode, "title");
|
||||
author = Book.getTextNode(rootnode, "author");
|
||||
genre = Book.getTextNode(rootnode, "genre");
|
||||
comment = Book.getTextNode(rootnode, "comment");
|
||||
|
||||
File icon = new File(root, "coverart.png");
|
||||
if (!icon.exists()) {
|
||||
icon = new File(root, "coverart.jpg");
|
||||
}
|
||||
if (!icon.exists()) {
|
||||
icon = new File(root, "coverart.gif");
|
||||
}
|
||||
|
||||
if (icon.exists()) {
|
||||
cover = new ImageIcon(icon.getAbsolutePath());
|
||||
resizedCover = Utils.getScaledImage(cover.getImage(), 75, 75);
|
||||
iconLabel = new JLabel(new ImageIcon(resizedCover));
|
||||
} else {
|
||||
cover = null;
|
||||
resizedCover = null;
|
||||
iconLabel = new JLabel("");
|
||||
}
|
||||
|
||||
populate();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void loadBookData(Properties props, ImageIcon i) {
|
||||
try {
|
||||
name = props.getProperty("book.name");
|
||||
@@ -71,41 +151,44 @@ public class BookPanel extends JPanel {
|
||||
resizedCover = Utils.getScaledImage(cover.getImage(), 75, 75);
|
||||
iconLabel = new JLabel(new ImageIcon(resizedCover));
|
||||
}
|
||||
|
||||
iconLabel.setSize(new Dimension(75, 75));
|
||||
iconLabel.setPreferredSize(new Dimension(75, 75));
|
||||
|
||||
titleLabel = new JLabel(name);
|
||||
authorLabel = new JLabel(author);
|
||||
otherLabel = new JLabel(genre + " :: " + comment);
|
||||
|
||||
authorLabel.setForeground(new Color(0x80, 0x80, 0x80));
|
||||
otherLabel.setForeground(new Color(0x80, 0x80, 0x80));
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
panel = new JPanel();
|
||||
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
|
||||
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||
|
||||
panel.add(titleLabel);
|
||||
panel.add(authorLabel);
|
||||
panel.add(otherLabel);
|
||||
|
||||
add(iconLabel, BorderLayout.WEST);
|
||||
add(panel, BorderLayout.CENTER);
|
||||
panel.setBackground(new Color(0x20, 0x20, 0x20));
|
||||
panel.setOpaque(true);
|
||||
setBackground(new Color(0x20, 0x20, 0x20));
|
||||
setOpaque(true);
|
||||
populate();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
void populate() {
|
||||
iconLabel.setSize(new Dimension(75, 75));
|
||||
iconLabel.setPreferredSize(new Dimension(75, 75));
|
||||
|
||||
titleLabel = new JLabel(name);
|
||||
authorLabel = new JLabel(author);
|
||||
otherLabel = new JLabel(genre + " :: " + comment);
|
||||
|
||||
authorLabel.setForeground(new Color(0x80, 0x80, 0x80));
|
||||
otherLabel.setForeground(new Color(0x80, 0x80, 0x80));
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
panel = new JPanel();
|
||||
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
|
||||
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||
|
||||
panel.add(titleLabel);
|
||||
panel.add(authorLabel);
|
||||
panel.add(otherLabel);
|
||||
|
||||
add(iconLabel, BorderLayout.WEST);
|
||||
add(panel, BorderLayout.CENTER);
|
||||
panel.setBackground(new Color(0x20, 0x20, 0x20));
|
||||
panel.setOpaque(true);
|
||||
setBackground(new Color(0x20, 0x20, 0x20));
|
||||
setOpaque(true);
|
||||
}
|
||||
|
||||
public File getConfigFile() {
|
||||
return new File(root, "audiobook.abk");
|
||||
return configFile;
|
||||
}
|
||||
|
||||
public void highlight() {
|
||||
|
||||
20
src/uk/co/majenko/audiobookrecorder/BookTreeNode.java
Normal file
20
src/uk/co/majenko/audiobookrecorder/BookTreeNode.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package uk.co.majenko.audiobookrecorder;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public abstract class BookTreeNode extends DefaultMutableTreeNode {
|
||||
|
||||
public BookTreeNode(String t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
public BookTreeNode() {
|
||||
super("");
|
||||
}
|
||||
|
||||
public abstract void setNotes(String t);
|
||||
public abstract String getNotes();
|
||||
|
||||
public abstract void onSelect();
|
||||
}
|
||||
|
||||
@@ -9,24 +9,32 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
||||
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
JLabel ret = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
ret.setIconTextGap(0);
|
||||
ret.setIconTextGap(5);
|
||||
ret.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
if (value instanceof Sentence) {
|
||||
Sentence s = (Sentence)value;
|
||||
|
||||
JPanel p = new JPanel();
|
||||
p.setLayout(new GridBagLayout());
|
||||
GridBagConstraints ctx = new GridBagConstraints();
|
||||
|
||||
OverlayIcon icn = new OverlayIcon(Icons.sentence);
|
||||
|
||||
if (s.getOverrideText() != null) {
|
||||
ret.setText(s.getOverrideText());
|
||||
}
|
||||
|
||||
if (!s.isProcessed()) {
|
||||
ret.setForeground(new Color(0x88, 0x88, 0x88));
|
||||
}
|
||||
|
||||
if (s.getAttentionFlag()) {
|
||||
ret.setForeground(new Color(0xFF, 0xFF, 0x00));
|
||||
icn.add(Overlays.attention, OverlayIcon.TOP_LEFT);
|
||||
}
|
||||
|
||||
if (s.isLocked()) {
|
||||
ret.setForeground(new Color(0x00, 0x80, 0xFF));
|
||||
ret.setForeground(new Color(0x30, 0xb0, 0xFF));
|
||||
icn.add(Overlays.locked, OverlayIcon.BOTTOM_LEFT);
|
||||
}
|
||||
|
||||
@@ -34,6 +42,10 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
||||
icn.add(Overlays.important, OverlayIcon.TOP_RIGHT);
|
||||
}
|
||||
|
||||
if (s.getEndOffset() == s.getSampleSize() - 1) {
|
||||
icn.add(Overlays.important, OverlayIcon.TOP_RIGHT);
|
||||
}
|
||||
|
||||
if (s.getEffectChain() != null) {
|
||||
if (!s.getEffectChain().equals("none")) {
|
||||
icn.add(Overlays.filter, OverlayIcon.BOTTOM_RIGHT);
|
||||
@@ -55,17 +67,83 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
||||
}
|
||||
|
||||
if (gaptype.equals("sentence")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
p.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
} else if (gaptype.equals("continuation")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
p.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
} else if (gaptype.equals("paragraph")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 7, 0));
|
||||
p.setBorder(new EmptyBorder(0, 0, 7, 0));
|
||||
} else if (gaptype.equals("section")) {
|
||||
ret.setBorder(new EmptyBorder(0, 0, 15, 0));
|
||||
p.setBorder(new EmptyBorder(0, 0, 15, 0));
|
||||
}
|
||||
|
||||
|
||||
JLabel time = new JLabel(Utils.secToTime(s.getLength(), "mm:ss.SSS") + " ");
|
||||
|
||||
ctx.gridx = 0;
|
||||
ctx.gridy = 0;
|
||||
ctx.fill = GridBagConstraints.HORIZONTAL;
|
||||
ctx.anchor = GridBagConstraints.LINE_START;
|
||||
|
||||
String effectChain = s.getEffectChain();
|
||||
if ((effectChain == null) || (effectChain.equals("none"))) {
|
||||
ctx.weightx = 1.0d;
|
||||
ctx.gridwidth = 2;
|
||||
p.add(ret, ctx);
|
||||
} else {
|
||||
ctx.weightx = 1.0d;
|
||||
ctx.gridwidth = 1;
|
||||
p.add(ret, ctx);
|
||||
Effect e = AudiobookRecorder.window.effects.get(effectChain);
|
||||
JLabel eff = new JLabel(e.toString() + " ");
|
||||
ctx.weightx = 0.0d;
|
||||
ctx.gridwidth = 1;
|
||||
ctx.gridx = 1;
|
||||
p.add(eff);
|
||||
}
|
||||
|
||||
ctx.gridwidth = 1;
|
||||
ctx.weightx = 0.0d;
|
||||
ctx.gridx = 2;
|
||||
ctx.anchor = GridBagConstraints.LINE_END;
|
||||
int peak = s.getPeakDB();
|
||||
JLabel peakLabel = new JLabel(peak + "dB ");
|
||||
if (peak > 0) {
|
||||
peakLabel.setForeground(new Color(0xCC, 0x00, 0x00));
|
||||
}
|
||||
p.add(peakLabel, ctx);
|
||||
|
||||
ctx.weightx = 0.0d;
|
||||
ctx.gridx = 3;
|
||||
ctx.anchor = GridBagConstraints.LINE_END;
|
||||
p.add(time, ctx);
|
||||
|
||||
p.setOpaque(false);
|
||||
|
||||
return p;
|
||||
|
||||
} else if (value instanceof Chapter) {
|
||||
Chapter c = (Chapter)value;
|
||||
|
||||
ret.setIcon(Icons.chapter);
|
||||
|
||||
JPanel p = new JPanel();
|
||||
p.setLayout(new GridBagLayout());
|
||||
GridBagConstraints ctx = new GridBagConstraints();
|
||||
|
||||
JLabel time = new JLabel(Utils.secToTime(c.getLength(), "mm:ss") + " ");
|
||||
|
||||
ctx.gridx = 0;
|
||||
ctx.gridy = 0;
|
||||
ctx.fill = GridBagConstraints.HORIZONTAL;
|
||||
ctx.anchor = GridBagConstraints.LINE_START;
|
||||
ctx.weightx = 1.0d;
|
||||
p.add(ret, ctx);
|
||||
ctx.weightx = 0.0d;
|
||||
ctx.gridx = 1;
|
||||
ctx.anchor = GridBagConstraints.LINE_END;
|
||||
p.add(time, ctx);
|
||||
p.setOpaque(false);
|
||||
return p;
|
||||
} else if (value instanceof Book) {
|
||||
ret.setIcon(((Book)value).getIcon());
|
||||
}
|
||||
|
||||
@@ -34,4 +34,11 @@ public class CacheManager {
|
||||
cache.remove(c);
|
||||
c.clearCache();
|
||||
}
|
||||
|
||||
public static void purgeCache() {
|
||||
for (Cacheable c : cache) {
|
||||
c.clearCache();
|
||||
}
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,21 @@ import it.sauronsoftware.jave.*;
|
||||
import com.mpatric.mp3agic.*;
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
public class Chapter extends DefaultMutableTreeNode {
|
||||
public class Chapter extends BookTreeNode {
|
||||
|
||||
String name;
|
||||
String id;
|
||||
@@ -21,6 +34,8 @@ public class Chapter extends DefaultMutableTreeNode {
|
||||
int preGap;
|
||||
int postGap;
|
||||
|
||||
String notes;
|
||||
|
||||
public Chapter(String i, String chaptername) {
|
||||
super(chaptername);
|
||||
|
||||
@@ -28,7 +43,25 @@ public class Chapter extends DefaultMutableTreeNode {
|
||||
name = chaptername;
|
||||
preGap = Options.getInteger("catenation.pre-chapter");
|
||||
postGap = Options.getInteger("catenation.post-chapter");
|
||||
}
|
||||
|
||||
public Chapter(Element root, DefaultTreeModel model) {
|
||||
|
||||
name = Book.getTextNode(root, "name");
|
||||
id = root.getAttribute("id");
|
||||
preGap = Utils.s2i(Book.getTextNode(root, "pre-gap"));
|
||||
postGap = Utils.s2i(Book.getTextNode(root, "post-gap"));
|
||||
|
||||
notes = Book.getTextNode(root, "notes");
|
||||
|
||||
Element sentencesNode = Book.getNode(root, "sentences");
|
||||
NodeList sentences = sentencesNode.getElementsByTagName("sentence");
|
||||
|
||||
for (int i = 0; i < sentences.getLength(); i++) {
|
||||
Element sentenceElement = (Element)sentences.item(i);
|
||||
Sentence newSentence = new Sentence(sentenceElement);
|
||||
model.insertNodeInto(newSentence, this, getChildCount());
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
@@ -116,7 +149,7 @@ public class Chapter extends DefaultMutableTreeNode {
|
||||
audioAttributes.setCodec("libmp3lame");
|
||||
audioAttributes.setBitRate(Options.getInteger("audio.export.bitrate"));
|
||||
audioAttributes.setSamplingRate(Options.getInteger("audio.export.samplerate"));
|
||||
audioAttributes.setChannels(2); //new Integer(2));
|
||||
audioAttributes.setChannels(Options.getInteger("audio.export.channels")); //new Integer(2));
|
||||
attributes.setFormat("mp3");
|
||||
attributes.setAudioAttributes(audioAttributes);
|
||||
|
||||
@@ -239,4 +272,60 @@ public class Chapter extends DefaultMutableTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
public void purgeBackups() {
|
||||
for (Enumeration o = children(); o.hasMoreElements();) {
|
||||
Object ob = (Object)o.nextElement();
|
||||
if (ob instanceof Sentence) {
|
||||
Sentence s = (Sentence)ob;
|
||||
s.purgeBackups();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Element getChapterXML(Document doc) {
|
||||
Element chapterNode = doc.createElement("chapter");
|
||||
chapterNode.setAttribute("id", id);
|
||||
chapterNode.appendChild(Book.makeTextNode(doc, "name", name));
|
||||
chapterNode.appendChild(Book.makeTextNode(doc, "pre-gap", preGap));
|
||||
chapterNode.appendChild(Book.makeTextNode(doc, "post-gap", postGap));
|
||||
chapterNode.appendChild(Book.makeTextNode(doc, "notes", notes));
|
||||
|
||||
Element sentencesNode = doc.createElement("sentences");
|
||||
chapterNode.appendChild(sentencesNode);
|
||||
|
||||
for (Enumeration o = children(); o.hasMoreElements();) {
|
||||
Object ob = (Object)o.nextElement();
|
||||
if (ob instanceof Sentence) {
|
||||
Sentence s = (Sentence)ob;
|
||||
sentencesNode.appendChild(s.getSentenceXML(doc));
|
||||
}
|
||||
}
|
||||
|
||||
return chapterNode;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String t) {
|
||||
notes = t;
|
||||
}
|
||||
|
||||
public void onSelect() {
|
||||
AudiobookRecorder.window.setChapterNotes(notes);
|
||||
}
|
||||
|
||||
public double getLength() {
|
||||
double len = 0;
|
||||
for (Enumeration o = children(); o.hasMoreElements();) {
|
||||
Object ob = (Object)o.nextElement();
|
||||
if (ob instanceof Sentence) {
|
||||
Sentence s = (Sentence)ob;
|
||||
len += s.getLength();
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ public class Clipping implements Effect {
|
||||
}
|
||||
|
||||
public void process(double[][] samples) {
|
||||
for (double[] sample : samples) {
|
||||
if (sample[Sentence.LEFT] > clip) sample[Sentence.LEFT] = clip;
|
||||
if (sample[Sentence.LEFT] < -clip) sample[Sentence.LEFT] = -clip;
|
||||
if (sample[Sentence.RIGHT] > clip) sample[Sentence.RIGHT] = clip;
|
||||
if (sample[Sentence.RIGHT] < -clip) sample[Sentence.RIGHT] = -clip;
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
if (samples[Sentence.LEFT][i] > clip) samples[Sentence.LEFT][i] = clip;
|
||||
if (samples[Sentence.LEFT][i] < -clip) samples[Sentence.LEFT][i] = -clip;
|
||||
if (samples[Sentence.RIGHT][i] > clip) samples[Sentence.RIGHT][i] = clip;
|
||||
if (samples[Sentence.RIGHT][i] < -clip) samples[Sentence.RIGHT][i] = -clip;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
192
src/uk/co/majenko/audiobookrecorder/CommandLine.java
Normal file
192
src/uk/co/majenko/audiobookrecorder/CommandLine.java
Normal file
@@ -0,0 +1,192 @@
|
||||
package uk.co.majenko.audiobookrecorder;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class CommandLine {
|
||||
HashMap<String, Class<?>> parameterTypes = new HashMap<String, Class<?>>();
|
||||
HashMap<String, String> parameterComments = new HashMap<String, String>();
|
||||
HashMap<String, Object> parameterValues = new HashMap<String, Object>();
|
||||
HashMap<String, String> parameterNames = new HashMap<String, String>();
|
||||
ArrayList<String> extraValues = new ArrayList<String>();
|
||||
|
||||
public CommandLine() {
|
||||
}
|
||||
|
||||
public void addParameter(String key, String name, Class<?> type, String comment) {
|
||||
parameterNames.put(key, name);
|
||||
parameterTypes.put(key, type);
|
||||
parameterComments.put(key, comment);
|
||||
}
|
||||
|
||||
public String[] process(String[] args) {
|
||||
parameterValues = new HashMap<String, Object>();
|
||||
extraValues = new ArrayList<String>();
|
||||
|
||||
for (String arg : args) {
|
||||
if (arg.startsWith("--")) {
|
||||
arg = arg.substring(2);
|
||||
String value = "";
|
||||
int equals = arg.indexOf("=");
|
||||
if (equals > -1) {
|
||||
value = arg.substring(equals + 1);
|
||||
arg = arg.substring(0, equals);
|
||||
}
|
||||
|
||||
Class<?> aclass = parameterTypes.get(arg);
|
||||
if (aclass == null) {
|
||||
help();
|
||||
System.exit(0);
|
||||
}
|
||||
if (aclass == Boolean.class) {
|
||||
Boolean b = true;
|
||||
parameterValues.put(arg, b);
|
||||
continue;
|
||||
}
|
||||
if (value.equals("")) {
|
||||
help();
|
||||
System.exit(0);
|
||||
}
|
||||
if (aclass == Integer.class) {
|
||||
Integer i = 0;
|
||||
try {
|
||||
i = Integer.parseInt(value);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
parameterValues.put(arg, i);
|
||||
continue;
|
||||
}
|
||||
if (aclass == Float.class) {
|
||||
Float f = 0F;
|
||||
try {
|
||||
f = Float.parseFloat(value);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
parameterValues.put(arg, f);
|
||||
continue;
|
||||
}
|
||||
if (aclass == Double.class) {
|
||||
Double d = 0D;
|
||||
try {
|
||||
d = Double.parseDouble(value);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
parameterValues.put(arg, d);
|
||||
continue;
|
||||
}
|
||||
if (aclass == String.class) {
|
||||
parameterValues.put(arg, value);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
extraValues.add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return extraValues.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public void help() {
|
||||
System.out.println("Available command line arguments:");
|
||||
int maxlen = 0;
|
||||
|
||||
String[] arglist = parameterTypes.keySet().toArray(new String[0]);
|
||||
Arrays.sort(arglist);
|
||||
|
||||
for (String s : arglist) {
|
||||
int thislen = s.length();
|
||||
if (parameterTypes.get(s) != Boolean.class) {
|
||||
thislen++;
|
||||
thislen += parameterNames.get(s).length();
|
||||
}
|
||||
if (thislen > maxlen) {
|
||||
maxlen = thislen;
|
||||
}
|
||||
}
|
||||
for (String s : arglist) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
System.out.print(" --");
|
||||
sb.append(s);
|
||||
if (parameterTypes.get(s) != Boolean.class) {
|
||||
sb.append("=");
|
||||
sb.append(parameterNames.get(s));
|
||||
}
|
||||
while (sb.length() < maxlen) {
|
||||
sb.append(" ");
|
||||
}
|
||||
System.out.print(sb.toString());
|
||||
System.out.print(" ");
|
||||
System.out.println(parameterComments.get(s));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSet(String key) {
|
||||
Object value = parameterValues.get(key);
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
Class<?> type = parameterTypes.get(key);
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
if (type != String.class) {
|
||||
return null;
|
||||
}
|
||||
String value = (String)parameterValues.get(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getInteger(String key) {
|
||||
Class<?> type = parameterTypes.get(key);
|
||||
if (type == null) {
|
||||
return 0;
|
||||
}
|
||||
if (type != Integer.class) {
|
||||
return 0;
|
||||
}
|
||||
Integer value = (Integer)parameterValues.get(key);
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
public float getFloat(String key) {
|
||||
Class<?> type = parameterTypes.get(key);
|
||||
if (type == null) {
|
||||
return 0f;
|
||||
}
|
||||
if (type != Float.class) {
|
||||
return 0f;
|
||||
}
|
||||
Float value = (Float)parameterValues.get(key);
|
||||
if (value == null) {
|
||||
return 0f;
|
||||
}
|
||||
return (float)value;
|
||||
}
|
||||
|
||||
public double getDouble(String key) {
|
||||
Class<?> type = parameterTypes.get(key);
|
||||
if (type == null) {
|
||||
return 0d;
|
||||
}
|
||||
if (type != Double.class) {
|
||||
return 0d;
|
||||
}
|
||||
Double value = (Double)parameterValues.get(key);
|
||||
if (value == null) {
|
||||
return 0d;
|
||||
}
|
||||
return (double)value;
|
||||
}
|
||||
|
||||
public void set(String key, String value) {
|
||||
parameterValues.put(key, value);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,53 @@
|
||||
package uk.co.majenko.audiobookrecorder;
|
||||
|
||||
import java.util.Date;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
public class Debug {
|
||||
static long timestamp;
|
||||
static public boolean debugEnabled = false;
|
||||
static public boolean traceEnabled = false;
|
||||
|
||||
static void debug(String msg) {
|
||||
if (!debugEnabled) return;
|
||||
long now = System.currentTimeMillis();
|
||||
long diff = now - timestamp;
|
||||
timestamp = now;
|
||||
System.err.println(String.format("%8d - %s", diff, msg));
|
||||
}
|
||||
|
||||
static void d(Object... args) {
|
||||
if (!debugEnabled) return;
|
||||
|
||||
Thread t = Thread.currentThread();
|
||||
StackTraceElement[] st = t.getStackTrace();
|
||||
StackTraceElement caller = st[2];
|
||||
|
||||
String tag = "[" + getCurrentLocalDateTimeStamp() + "] " + caller.getFileName() + " " + caller.getLineNumber() + " (" + caller.getMethodName() + "):";
|
||||
|
||||
System.err.print(tag);
|
||||
|
||||
for (Object o : args) {
|
||||
System.err.print(" ");
|
||||
System.err.print(o);
|
||||
}
|
||||
System.err.println();
|
||||
}
|
||||
|
||||
static void trace() {
|
||||
if (!traceEnabled) return;
|
||||
Thread t = Thread.currentThread();
|
||||
StackTraceElement[] st = t.getStackTrace();
|
||||
StackTraceElement caller = st[3];
|
||||
StackTraceElement callee = st[2];
|
||||
|
||||
String tag = "[" + getCurrentLocalDateTimeStamp() + "] " + t.getName() + " - " + caller.getFileName() + ":" + caller.getLineNumber() + " " + caller.getMethodName() + "(...) -> " + callee.getFileName() + ":" + callee.getLineNumber() + " " + callee.getMethodName() + "(...)";
|
||||
|
||||
System.err.println(tag);
|
||||
}
|
||||
|
||||
public static String getCurrentLocalDateTimeStamp() {
|
||||
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,60 +17,50 @@ public class DelayLine implements Effect {
|
||||
}
|
||||
|
||||
public void process(double[][] samples) {
|
||||
double[][] savedSamples = new double[samples.length][2];
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
savedSamples[i][Sentence.LEFT] = samples[i][Sentence.LEFT];
|
||||
savedSamples[i][Sentence.RIGHT] = samples[i][Sentence.RIGHT];
|
||||
double[][] savedSamples = new double[2][samples[Sentence.LEFT].length];
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
savedSamples[Sentence.LEFT][i] = samples[Sentence.LEFT][i];
|
||||
savedSamples[Sentence.RIGHT][i] = samples[Sentence.RIGHT][i];
|
||||
}
|
||||
if (wetOnly) {
|
||||
for (int i = 0; i < samples.length; i++) {
|
||||
samples[i][Sentence.LEFT] = 0d;
|
||||
samples[i][Sentence.RIGHT] = 0d;
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
samples[Sentence.LEFT][i] = 0d;
|
||||
samples[Sentence.RIGHT][i] = 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];
|
||||
double[][] subSamples = new double[2][samples[Sentence.LEFT].length];
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
subSamples[Sentence.LEFT][i] = savedSamples[Sentence.LEFT][i];
|
||||
subSamples[Sentence.RIGHT][i] = savedSamples[Sentence.RIGHT][i];
|
||||
}
|
||||
for (DelayLineStore d : delayLines) {
|
||||
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 (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
subSamples[Sentence.LEFT][i] = savedSamples[Sentence.LEFT][i];
|
||||
subSamples[Sentence.RIGHT][i] = savedSamples[Sentence.RIGHT][i];
|
||||
}
|
||||
|
||||
d.process(subSamples);
|
||||
|
||||
for (int i = 0; i < subSamples.length; i++) {
|
||||
for (int i = 0; i < subSamples[Sentence.LEFT].length; i++) {
|
||||
int off = i + d.getSamples();
|
||||
if ((off < samples.length) && (off > 0)) {
|
||||
|
||||
double[] ns = mix(samples[off], subSamples[i]);
|
||||
samples[off][Sentence.LEFT] = ns[Sentence.LEFT];
|
||||
samples[off][Sentence.RIGHT] = ns[Sentence.RIGHT];
|
||||
if ((off < samples[Sentence.LEFT].length) && (off > 0)) {
|
||||
samples[Sentence.LEFT][off] = mix(samples[Sentence.LEFT][off], subSamples[Sentence.LEFT][i]);
|
||||
samples[Sentence.RIGHT][off] = mix(samples[Sentence.RIGHT][off], subSamples[Sentence.RIGHT][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double[] mix(double[] a, double[] b) {
|
||||
double[] out = new double[2];
|
||||
double mix(double a, double b) {
|
||||
double out;
|
||||
|
||||
if ((a[Sentence.LEFT] < 0) && (b[Sentence.LEFT] < 0)) {
|
||||
out[Sentence.LEFT] = (a[Sentence.LEFT] + b[Sentence.LEFT]) - (a[Sentence.LEFT] * b[Sentence.LEFT]);
|
||||
} else if ((a[Sentence.LEFT] > 0) && (b[Sentence.LEFT] > 0)) {
|
||||
out[Sentence.LEFT] = (a[Sentence.LEFT] + b[Sentence.LEFT]) - (a[Sentence.LEFT] * b[Sentence.LEFT]);
|
||||
if ((a < 0) && (b < 0)) {
|
||||
out = (a + b) - (a * b);
|
||||
} else if ((a > 0) && (b > 0)) {
|
||||
out = (a + b) - (a * b);
|
||||
} else {
|
||||
out[Sentence.LEFT] = a[Sentence.LEFT] + b[Sentence.LEFT];
|
||||
}
|
||||
|
||||
if ((a[Sentence.RIGHT] < 0) && (b[Sentence.RIGHT] < 0)) {
|
||||
out[Sentence.RIGHT] = (a[Sentence.RIGHT] + b[Sentence.RIGHT]) - (a[Sentence.RIGHT] * b[Sentence.RIGHT]);
|
||||
} else if ((a[Sentence.RIGHT] > 0) && (b[Sentence.RIGHT] > 0)) {
|
||||
out[Sentence.RIGHT] = (a[Sentence.RIGHT] + b[Sentence.RIGHT]) - (a[Sentence.RIGHT] * b[Sentence.RIGHT]);
|
||||
} else {
|
||||
out[Sentence.RIGHT] = a[Sentence.RIGHT] + b[Sentence.RIGHT];
|
||||
out = a + b;
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
@@ -29,16 +29,16 @@ public class DelayLineStore {
|
||||
e.process(samples);
|
||||
}
|
||||
|
||||
for (double[] sample : samples) {
|
||||
sample[Sentence.LEFT] *= gain;
|
||||
sample[Sentence.RIGHT] *= gain;
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
samples[Sentence.LEFT][i] *= gain;
|
||||
samples[Sentence.RIGHT][i] *= gain;
|
||||
|
||||
if (pan < 0) {
|
||||
double p = 1 + pan;
|
||||
sample[Sentence.RIGHT] *= p;
|
||||
samples[Sentence.RIGHT][i] *= p;
|
||||
} else {
|
||||
double p = 1 - pan;
|
||||
sample[Sentence.LEFT] *= p;
|
||||
samples[Sentence.LEFT][i] *= p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +38,5 @@ public class Icons {
|
||||
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"));
|
||||
static public final ImageIcon manuscript = new ImageIcon(Icons.class.getResource("icons/manuscript.png"));
|
||||
}
|
||||
|
||||
@@ -9,37 +9,73 @@ public class LFO implements Effect {
|
||||
double depth;
|
||||
double sampleRate;
|
||||
double sampleStep;
|
||||
int waveform;
|
||||
double duty;
|
||||
int mode;
|
||||
|
||||
public static final int SINE = 0;
|
||||
public static final int COSINE = 1;
|
||||
public static final int SQUARE = 2;
|
||||
public static final int TRIANGLE = 3;
|
||||
public static final int SAWTOOTH = 4;
|
||||
|
||||
public static final int ADD = 0;
|
||||
public static final int REPLACE = 1;
|
||||
|
||||
public LFO(double f, double d) {
|
||||
frequency = f;
|
||||
depth = d;
|
||||
phase = 0;
|
||||
this(f, d, 0, SINE, Math.PI, REPLACE);
|
||||
}
|
||||
|
||||
public LFO(double f, double d, double p) {
|
||||
this(f, d, p, SINE, Math.PI, REPLACE);
|
||||
}
|
||||
|
||||
public LFO(double f, double d, double p, int w) {
|
||||
this(f, d, p, w, Math.PI, REPLACE);
|
||||
}
|
||||
|
||||
public LFO(double f, double d, double p, int w, double dty) {
|
||||
this(f, d, p, w, dty, REPLACE);
|
||||
}
|
||||
|
||||
public LFO(double f, double d, double p, int w, double dty, int m) {
|
||||
frequency = f;
|
||||
depth = d;
|
||||
phase = p;
|
||||
waveform = w;
|
||||
duty = dty;
|
||||
mode = m;
|
||||
}
|
||||
|
||||
public void process(double[][] samples) {
|
||||
for (double[] sample : samples) {
|
||||
double v = Math.sin(phase);
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
double v = 0;
|
||||
switch (waveform) {
|
||||
case SINE: v = Math.sin(phase); break;
|
||||
case COSINE: v = Math.cos(phase); break;
|
||||
case SQUARE: v = (phase > duty) ? 1d : 0d; break;
|
||||
case TRIANGLE: v = (phase < Math.PI) ? (phase / Math.PI) : (1d - ((phase - Math.PI) / Math.PI)); break;
|
||||
case SAWTOOTH: v = (phase / (Math.PI*2d)); break;
|
||||
}
|
||||
phase += sampleStep;
|
||||
if (phase > (Math.PI * 2d)) {
|
||||
phase -= (Math.PI * 2d);
|
||||
}
|
||||
|
||||
// // Make it between 0 and 1.
|
||||
// v = 1d + v;
|
||||
// v /= 2d;
|
||||
|
||||
// Multiply it by the gain factor
|
||||
v *= depth;
|
||||
|
||||
// Apply it to the sample
|
||||
sample[Sentence.LEFT] += (sample[Sentence.LEFT] * v);
|
||||
sample[Sentence.RIGHT] += (sample[Sentence.RIGHT] * v);
|
||||
switch (mode) {
|
||||
case REPLACE:
|
||||
samples[Sentence.LEFT][i] = (samples[Sentence.LEFT][i] * v);
|
||||
samples[Sentence.RIGHT][i] = (samples[Sentence.RIGHT][i] * v);
|
||||
break;
|
||||
case ADD:
|
||||
samples[Sentence.LEFT][i] += (samples[Sentence.LEFT][i] * v);
|
||||
samples[Sentence.RIGHT][i] += (samples[Sentence.RIGHT][i] * v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,11 @@ public class MainToolBar extends JToolBar {
|
||||
JButtonSpacePlay playtoSentence;
|
||||
JButtonSpacePlay stopPlaying;
|
||||
JButtonSpacePlay eq;
|
||||
JButtonSpacePlay openManuscript;
|
||||
JToggleButtonSpacePlay mic;
|
||||
|
||||
JComboBox<String> playbackSpeed;
|
||||
|
||||
JToggleButtonSpacePlay disableEffects;
|
||||
|
||||
AudiobookRecorder root;
|
||||
@@ -100,6 +103,7 @@ public class MainToolBar extends JToolBar {
|
||||
eq = new JButtonSpacePlay(Icons.eq, "Reload Effects", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
root.loadEffects();
|
||||
CacheManager.purgeCache();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -128,6 +132,7 @@ public class MainToolBar extends JToolBar {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
add(mic);
|
||||
|
||||
@@ -152,6 +157,28 @@ public class MainToolBar extends JToolBar {
|
||||
|
||||
add(disableEffects);
|
||||
|
||||
addSeparator();
|
||||
|
||||
add(new JLabel("Playback speed: "));
|
||||
playbackSpeed = new JComboBox<String>(new String[] {
|
||||
"0.75x",
|
||||
"1.00x",
|
||||
"1.25x",
|
||||
"1.50x",
|
||||
"1.75x"
|
||||
});
|
||||
playbackSpeed.setFocusable(false);
|
||||
|
||||
playbackSpeed.setSelectedIndex(1);
|
||||
add(playbackSpeed);
|
||||
|
||||
addSeparator();
|
||||
openManuscript = new JButtonSpacePlay(Icons.manuscript, "Open Manuscript", new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
root.openManuscript();
|
||||
}
|
||||
});
|
||||
add(openManuscript);
|
||||
|
||||
|
||||
setFloatable(false);
|
||||
@@ -161,4 +188,9 @@ public class MainToolBar extends JToolBar {
|
||||
playtoSentence.setEnabled(b);
|
||||
}
|
||||
|
||||
public float getPlaybackSpeed() {
|
||||
int v = playbackSpeed.getSelectedIndex();
|
||||
return 0.75f + (0.25f * v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,10 +86,16 @@ public class OpenBookPanel extends JPanel {
|
||||
for (File b : dir.listFiles()) {
|
||||
if (b == null) continue;
|
||||
if (!b.isDirectory()) continue;
|
||||
File xml = new File(b, "audiobook.abk");
|
||||
File xml = new File(b, "audiobook.abx");
|
||||
if (xml.exists()) {
|
||||
BookPanel book = new BookPanel(b);
|
||||
model.addBook(book);
|
||||
} else {
|
||||
xml = new File(b, "audiobook.abk");
|
||||
if (xml.exists()) {
|
||||
BookPanel book = new BookPanel(b);
|
||||
model.addBook(book);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ public class Options extends JDialog {
|
||||
JComboBox<KVPair> rateList;
|
||||
JComboBox<KVPair> bitDepth;
|
||||
JComboBox<KVPair> trimMethod;
|
||||
JComboBox<KVPair> fftBlockSize;
|
||||
JComboBox<KVPair> playbackBlockSize;
|
||||
JTextField storageFolder;
|
||||
JTextField archiveFolder;
|
||||
JSpinner preChapterGap;
|
||||
@@ -32,8 +34,10 @@ public class Options extends JDialog {
|
||||
JSpinner shortSentenceGap;
|
||||
JSpinner postParagraphGap;
|
||||
JSpinner postSectionGap;
|
||||
JSpinner maxGainVariance;
|
||||
JTextField ffmpegLocation;
|
||||
JComboBox<KVPair> bitRate;
|
||||
JComboBox<KVPair> channels;
|
||||
JComboBox<KVPair> exportRate;
|
||||
JCheckBox enableParsing;
|
||||
JSpinner cacheSize;
|
||||
@@ -297,10 +301,13 @@ public class Options extends JDialog {
|
||||
bitDepth = addDropdown(optionsPanel, "Sample resolution:", getResolutionList(), get("audio.recording.resolution"));
|
||||
trimMethod = addDropdown(optionsPanel, "Auto-trim method:", getTrimMethods(), get("audio.recording.trim"));
|
||||
fftThreshold = addSpinner(optionsPanel, "FFT threshold:", 0, 100, 1, getInteger("audio.recording.trim.fft"), "");
|
||||
fftBlockSize = addDropdown(optionsPanel, "FFT Block size:", getFFTBlockSizes(), get("audio.recording.trim.blocksize"));
|
||||
maxGainVariance = addSpinner(optionsPanel, "Maximum gain variance:", 0, 100, 1, getInteger("audio.recording.variance"), "");
|
||||
|
||||
addSeparator(optionsPanel);
|
||||
|
||||
playbackList = addDropdown(optionsPanel, "Playback device:", getPlaybackMixerList(), get("audio.playback.device"));
|
||||
playbackBlockSize = addDropdown(optionsPanel, "Playback Block size:", getPlaybackBlockSizes(), get("audio.playback.blocksize"));
|
||||
addSeparator(optionsPanel);
|
||||
storageFolder = addFilePath(optionsPanel, "Storage folder:", get("path.storage"), true);
|
||||
archiveFolder = addFilePath(optionsPanel, "Archive folder:", get("path.archive"), true);
|
||||
@@ -318,6 +325,7 @@ public class Options extends JDialog {
|
||||
|
||||
ffmpegLocation = addFilePath(optionsPanel, "FFMPEG location:", get("path.ffmpeg"), false);
|
||||
bitRate = addDropdown(optionsPanel, "Export bitrate:", getBitrates(), get("audio.export.bitrate"));
|
||||
channels = addDropdown(optionsPanel, "Export channels:", getChannelCountList(), get("audio.export.channels"));
|
||||
exportRate = addDropdown(optionsPanel, "Export sample rate:", getSampleRateList(), get("audio.export.samplerate"));
|
||||
|
||||
|
||||
@@ -565,6 +573,8 @@ public class Options extends JDialog {
|
||||
} else {
|
||||
defaultPrefs.put("audio.playback.device", "");
|
||||
}
|
||||
defaultPrefs.put("audio.recording.trim.blocksize", "4096");
|
||||
defaultPrefs.put("audio.playback.blocksize", "4096");
|
||||
|
||||
defaultPrefs.put("catenation.pre-chapter", "1000");
|
||||
defaultPrefs.put("catenation.post-chapter", "1500");
|
||||
@@ -574,12 +584,14 @@ public class Options extends JDialog {
|
||||
defaultPrefs.put("catenation.post-section", "3000");
|
||||
|
||||
defaultPrefs.put("audio.recording.trim.fft", "10");
|
||||
defaultPrefs.put("audio.recording.variance", "10");
|
||||
|
||||
defaultPrefs.put("path.storage", (new File(System.getProperty("user.home"), "Recordings")).toString());
|
||||
defaultPrefs.put("path.archive", (new File(new File(System.getProperty("user.home"), "Recordings"),"archive")).toString());
|
||||
defaultPrefs.put("path.ffmpeg", "");
|
||||
|
||||
defaultPrefs.put("audio.export.bitrate", "256000");
|
||||
defaultPrefs.put("audio.export.channels", "2");
|
||||
defaultPrefs.put("audio.export.samplerate", "44100");
|
||||
defaultPrefs.put("process.sphinx", "false");
|
||||
|
||||
@@ -703,11 +715,15 @@ public class Options extends JDialog {
|
||||
set("catenation.post-paragraph", postParagraphGap.getValue());
|
||||
set("catenation.post-section", postSectionGap.getValue());
|
||||
set("audio.export.bitrate", ((KVPair)bitRate.getSelectedItem()).key);
|
||||
set("audio.export.channels", ((KVPair)channels.getSelectedItem()).key);
|
||||
set("audio.export.samplerate", ((KVPair)exportRate.getSelectedItem()).key);
|
||||
set("process.sphinx", enableParsing.isSelected());
|
||||
set("editor.external", externalEditor.getText());
|
||||
set("cache.size", cacheSize.getValue());
|
||||
set("audio.recording.trim.fft", fftThreshold.getValue());
|
||||
set("audio.recording.variance", maxGainVariance.getValue());
|
||||
set("audio.recording.trim.blocksize", ((KVPair)fftBlockSize.getSelectedItem()).key);
|
||||
set("audio.playback.blocksize", ((KVPair)playbackBlockSize.getSelectedItem()).key);
|
||||
|
||||
set("effects.ethereal.offset", etherealOffset.getValue());
|
||||
set("effects.ethereal.iterations", etherealIterations.getValue());
|
||||
@@ -782,6 +798,31 @@ public class Options extends JDialog {
|
||||
return pairs;
|
||||
}
|
||||
|
||||
public static KVPair[] getFFTBlockSizes() {
|
||||
KVPair[] pairs = new KVPair[8];
|
||||
pairs[0] = new KVPair<String, String>("1024", "1024");
|
||||
pairs[1] = new KVPair<String, String>("2048", "2048");
|
||||
pairs[2] = new KVPair<String, String>("4096", "4096");
|
||||
pairs[3] = new KVPair<String, String>("8192", "8192");
|
||||
pairs[4] = new KVPair<String, String>("16384", "16384");
|
||||
pairs[5] = new KVPair<String, String>("32768", "32768");
|
||||
pairs[6] = new KVPair<String, String>("65536", "65537");
|
||||
pairs[7] = new KVPair<String, String>("131072", "131072");
|
||||
return pairs;
|
||||
}
|
||||
|
||||
public static KVPair[] getPlaybackBlockSizes() {
|
||||
KVPair[] pairs = new KVPair[8];
|
||||
pairs[0] = new KVPair<String, String>("1024", "1024");
|
||||
pairs[1] = new KVPair<String, String>("2048", "2048");
|
||||
pairs[2] = new KVPair<String, String>("4096", "4096");
|
||||
pairs[3] = new KVPair<String, String>("8192", "8192");
|
||||
pairs[4] = new KVPair<String, String>("16384", "16384");
|
||||
pairs[5] = new KVPair<String, String>("32768", "32768");
|
||||
pairs[6] = new KVPair<String, String>("65536", "65537");
|
||||
pairs[7] = new KVPair<String, String>("131072", "131072");
|
||||
return pairs;
|
||||
}
|
||||
|
||||
public static void createEffectChains() {
|
||||
effectChains = new ArrayList<EffectGroup>();
|
||||
|
||||
@@ -20,13 +20,13 @@ public class Pan implements Effect {
|
||||
}
|
||||
|
||||
public void process(double[][] samples) {
|
||||
for (double[] sample : samples) {
|
||||
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
|
||||
if (pan < 0) {
|
||||
double p = 1 + pan;
|
||||
sample[Sentence.RIGHT] *= p;
|
||||
samples[Sentence.RIGHT][i] *= p;
|
||||
} else {
|
||||
double p = 1 - pan;
|
||||
sample[Sentence.LEFT] *= p;
|
||||
samples[Sentence.LEFT][i] *= p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,8 @@ import java.util.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
public class Utils {
|
||||
public static Image getScaledImage(Image srcImg, int w, int h){
|
||||
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
@@ -76,4 +78,12 @@ public class Utils {
|
||||
Runtime.getRuntime().freeMemory()
|
||||
));
|
||||
}
|
||||
|
||||
public static String secToTime(double sec, String fmt) {
|
||||
Date d = new Date((long)(sec * 1000d));
|
||||
SimpleDateFormat df = new SimpleDateFormat(fmt);
|
||||
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
String time = df.format(d);
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
int offsetFactor = 0;
|
||||
int offset = 0;
|
||||
|
||||
String loadedId = null;
|
||||
|
||||
ArrayList<MarkerDragListener> markerDragListeners;
|
||||
|
||||
public Waveform() {
|
||||
@@ -79,7 +81,7 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
|
||||
if (samples != null) {
|
||||
|
||||
int num = samples.length;
|
||||
int num = samples[Sentence.LEFT].length;
|
||||
step = num / zoomFactor / w;
|
||||
if (step == 0) return;
|
||||
|
||||
@@ -97,7 +99,8 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
double lmax = 0;
|
||||
|
||||
for (int o = 0; o < step; o++) {
|
||||
double sample = (samples[offset + (n * step) + o][Sentence.LEFT] + samples[offset + (n * step) + o][Sentence.RIGHT]) / 2d;
|
||||
if (offset + (n * step) + o >= samples[Sentence.LEFT].length) break;
|
||||
double sample = (samples[Sentence.LEFT][offset + (n * step) + o] + samples[Sentence.RIGHT][offset + (n * step) + o]) / 2d;
|
||||
if (sample >= 0) {
|
||||
have += sample;
|
||||
hcnt++;
|
||||
@@ -386,4 +389,12 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
|
||||
public int getCutEnd() {
|
||||
return cutExit;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
loadedId = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return loadedId;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user