Compare commits

..

16 Commits

23 changed files with 1447 additions and 283 deletions

View File

@@ -1 +1 @@
version=0.3.1 version=0.3.5

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -27,9 +27,9 @@ public class AGC implements Effect {
public void process(double[][] samples) { public void process(double[][] samples) {
gain = 1d; gain = 1d;
for (int i = 0; i < samples.length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
double absSampleLeft = Math.abs(samples[i][Sentence.LEFT]) * gain; double absSampleLeft = Math.abs(samples[Sentence.LEFT][i]) * gain;
double absSampleRight = Math.abs(samples[i][Sentence.RIGHT]) * gain; double absSampleRight = Math.abs(samples[Sentence.RIGHT][i]) * gain;
double factor = 0.0d; double factor = 0.0d;
@@ -49,8 +49,8 @@ public class AGC implements Effect {
if (gain > limit) gain = limit; if (gain > limit) gain = limit;
if (gain < 0) gain = 0; if (gain < 0) gain = 0;
samples[i][Sentence.LEFT] *= gain; samples[Sentence.LEFT][i] *= gain;
samples[i][Sentence.RIGHT] *= gain; samples[Sentence.RIGHT][i] *= gain;
} }
} }

View File

@@ -20,9 +20,9 @@ public class Amplifier implements Effect {
} }
public void process(double[][] samples) { public void process(double[][] samples) {
for (int i = 0; i < samples.length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
samples[i][Sentence.LEFT] *= gain; samples[Sentence.LEFT][i] *= gain;
samples[i][Sentence.RIGHT] *= gain; samples[Sentence.RIGHT][i] *= gain;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -94,19 +94,19 @@ public class Biquad implements Effect {
lz2 = 0d; lz2 = 0d;
rz1 = 0d; rz1 = 0d;
rz2 = 0d; rz2 = 0d;
for (double[] in : samples) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
double lout = in[Sentence.LEFT] * a0 + lz1; double lout = samples[Sentence.LEFT][i] * a0 + lz1;
lz1 = in[Sentence.LEFT] * a1 + lz2 - b1 * lout; lz1 = samples[Sentence.LEFT][i] * a1 + lz2 - b1 * lout;
lz2 = in[Sentence.LEFT] * a2 - b2 * 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; rz1 = samples[Sentence.RIGHT][i] * a1 + rz2 - b1 * rout;
rz2 = in[Sentence.RIGHT] * a2 - b2 * rout; rz2 = samples[Sentence.RIGHT][i] * a2 - b2 * rout;
in[Sentence.LEFT] = lout; samples[Sentence.LEFT][i] = lout;
in[Sentence.RIGHT] = rout; samples[Sentence.RIGHT][i] = rout;
} }
} }

View File

@@ -31,6 +31,7 @@ public class Book extends DefaultMutableTreeNode {
String genre; String genre;
String comment; String comment;
String ACX; String ACX;
String manuscript;
String defaultEffect = "none"; String defaultEffect = "none";
@@ -63,8 +64,9 @@ public class Book extends DefaultMutableTreeNode {
genre = getTextNode(root, "genre"); genre = getTextNode(root, "genre");
comment = getTextNode(root, "comment"); comment = getTextNode(root, "comment");
ACX = getTextNode(root, "acx"); ACX = getTextNode(root, "acx");
manuscript = getTextNode(root, "manuscript");
AudiobookRecorder.window.setNotes(getTextNode(root, "notes")); AudiobookRecorder.window.setBookNotes(getTextNode(root, "notes"));
Element settings = getNode(root, "settings"); Element settings = getNode(root, "settings");
Element audioSettings = getNode(settings, "audio"); Element audioSettings = getNode(settings, "audio");
@@ -97,8 +99,12 @@ public class Book extends DefaultMutableTreeNode {
} }
public static String getTextNode(Element r, String n) { 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); Element node = getNode(r, n);
if (node == null) return ""; if (node == null) return d;
return node.getTextContent(); return node.getTextContent();
} }
@@ -183,8 +189,12 @@ public class Book extends DefaultMutableTreeNode {
} }
} }
public File getBookPath() {
return new File(Options.get("path.storage"), name);
}
public void renameBook(String newName) { 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); File newDir = new File(Options.get("path.storage"), newName);
if (newDir.exists()) { if (newDir.exists()) {
@@ -298,8 +308,9 @@ public class Book extends DefaultMutableTreeNode {
root.appendChild(makeTextNode(doc, "comment", comment)); root.appendChild(makeTextNode(doc, "comment", comment));
root.appendChild(makeTextNode(doc, "genre", genre)); root.appendChild(makeTextNode(doc, "genre", genre));
root.appendChild(makeTextNode(doc, "acx", ACX)); root.appendChild(makeTextNode(doc, "acx", ACX));
root.appendChild(makeTextNode(doc, "manuscript", manuscript));
root.appendChild(makeTextNode(doc, "notes", AudiobookRecorder.window.getNotes())); root.appendChild(makeTextNode(doc, "notes", AudiobookRecorder.window.getBookNotes()));
Element settingsNode = doc.createElement("settings"); Element settingsNode = doc.createElement("settings");
root.appendChild(settingsNode); root.appendChild(settingsNode);
@@ -333,7 +344,7 @@ public class Book extends DefaultMutableTreeNode {
public static Element makeTextNode(Document doc, String name, String text) { public static Element makeTextNode(Document doc, String name, String text) {
Element node = doc.createElement(name); Element node = doc.createElement(name);
Text tnode = doc.createTextNode(text); Text tnode = doc.createTextNode(text == null ? "" : text);
node.appendChild(tnode); node.appendChild(tnode);
return node; return node;
} }
@@ -367,4 +378,24 @@ public class Book extends DefaultMutableTreeNode {
defaultEffect = 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;
}
} }

View 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();
}

View File

@@ -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) { 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.setIconTextGap(5);
ret.setBorder(new EmptyBorder(0, 0, 0, 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;
JPanel p = new JPanel();
p.setLayout(new GridBagLayout());
GridBagConstraints ctx = new GridBagConstraints();
OverlayIcon icn = new OverlayIcon(Icons.sentence); OverlayIcon icn = new OverlayIcon(Icons.sentence);
if (s.getOverrideText() != null) { if (s.getOverrideText() != null) {
ret.setText(s.getOverrideText()); ret.setText(s.getOverrideText());
} }
if (!s.isProcessed()) {
ret.setForeground(new Color(0x88, 0x88, 0x88));
}
if (s.getAttentionFlag()) { if (s.getAttentionFlag()) {
ret.setForeground(new Color(0xFF, 0xFF, 0x00)); ret.setForeground(new Color(0xFF, 0xFF, 0x00));
icn.add(Overlays.attention, OverlayIcon.TOP_LEFT); icn.add(Overlays.attention, OverlayIcon.TOP_LEFT);
} }
if (s.isLocked()) { if (s.isLocked()) {
ret.setForeground(new Color(0x00, 0x80, 0xFF)); ret.setForeground(new Color(0x30, 0xb0, 0xFF));
icn.add(Overlays.locked, OverlayIcon.BOTTOM_LEFT); icn.add(Overlays.locked, OverlayIcon.BOTTOM_LEFT);
} }
@@ -59,17 +67,83 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
} }
if (gaptype.equals("sentence")) { 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")) { } 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")) { } 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")) { } 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) { } else if (value instanceof Chapter) {
Chapter c = (Chapter)value;
ret.setIcon(Icons.chapter); 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) { } else if (value instanceof Book) {
ret.setIcon(((Book)value).getIcon()); ret.setIcon(((Book)value).getIcon());
} }

View File

@@ -26,7 +26,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.w3c.dom.Text; import org.w3c.dom.Text;
public class Chapter extends DefaultMutableTreeNode { public class Chapter extends BookTreeNode {
String name; String name;
String id; String id;
@@ -34,6 +34,8 @@ public class Chapter extends DefaultMutableTreeNode {
int preGap; int preGap;
int postGap; int postGap;
String notes;
public Chapter(String i, String chaptername) { public Chapter(String i, String chaptername) {
super(chaptername); super(chaptername);
@@ -49,6 +51,8 @@ public class Chapter extends DefaultMutableTreeNode {
id = root.getAttribute("id"); id = root.getAttribute("id");
preGap = Utils.s2i(Book.getTextNode(root, "pre-gap")); preGap = Utils.s2i(Book.getTextNode(root, "pre-gap"));
postGap = Utils.s2i(Book.getTextNode(root, "post-gap")); postGap = Utils.s2i(Book.getTextNode(root, "post-gap"));
notes = Book.getTextNode(root, "notes");
Element sentencesNode = Book.getNode(root, "sentences"); Element sentencesNode = Book.getNode(root, "sentences");
NodeList sentences = sentencesNode.getElementsByTagName("sentence"); NodeList sentences = sentencesNode.getElementsByTagName("sentence");
@@ -284,6 +288,7 @@ public class Chapter extends DefaultMutableTreeNode {
chapterNode.appendChild(Book.makeTextNode(doc, "name", name)); chapterNode.appendChild(Book.makeTextNode(doc, "name", name));
chapterNode.appendChild(Book.makeTextNode(doc, "pre-gap", preGap)); chapterNode.appendChild(Book.makeTextNode(doc, "pre-gap", preGap));
chapterNode.appendChild(Book.makeTextNode(doc, "post-gap", postGap)); chapterNode.appendChild(Book.makeTextNode(doc, "post-gap", postGap));
chapterNode.appendChild(Book.makeTextNode(doc, "notes", notes));
Element sentencesNode = doc.createElement("sentences"); Element sentencesNode = doc.createElement("sentences");
chapterNode.appendChild(sentencesNode); chapterNode.appendChild(sentencesNode);
@@ -299,4 +304,28 @@ public class Chapter extends DefaultMutableTreeNode {
return chapterNode; 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;
}
} }

View File

@@ -20,11 +20,11 @@ public class Clipping implements Effect {
} }
public void process(double[][] samples) { public void process(double[][] samples) {
for (double[] sample : samples) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
if (sample[Sentence.LEFT] > clip) sample[Sentence.LEFT] = clip; if (samples[Sentence.LEFT][i] > clip) samples[Sentence.LEFT][i] = clip;
if (sample[Sentence.LEFT] < -clip) sample[Sentence.LEFT] = -clip; if (samples[Sentence.LEFT][i] < -clip) samples[Sentence.LEFT][i] = -clip;
if (sample[Sentence.RIGHT] > clip) sample[Sentence.RIGHT] = clip; if (samples[Sentence.RIGHT][i] > clip) samples[Sentence.RIGHT][i] = clip;
if (sample[Sentence.RIGHT] < -clip) sample[Sentence.RIGHT] = -clip; if (samples[Sentence.RIGHT][i] < -clip) samples[Sentence.RIGHT][i] = -clip;
} }
} }

View 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);
}
}

View File

@@ -1,12 +1,53 @@
package uk.co.majenko.audiobookrecorder; package uk.co.majenko.audiobookrecorder;
import java.util.Date;
import java.text.SimpleDateFormat;
public class Debug { public class Debug {
static long timestamp; static long timestamp;
static public boolean debugEnabled = false;
static public boolean traceEnabled = false;
static void debug(String msg) { static void debug(String msg) {
if (!debugEnabled) return;
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
long diff = now - timestamp; long diff = now - timestamp;
timestamp = now; timestamp = now;
System.err.println(String.format("%8d - %s", diff, msg)); 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());
}
} }

View File

@@ -17,60 +17,50 @@ public class DelayLine implements Effect {
} }
public void process(double[][] samples) { public void process(double[][] samples) {
double[][] savedSamples = new double[samples.length][2]; double[][] savedSamples = new double[2][samples[Sentence.LEFT].length];
for (int i = 0; i < samples.length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
savedSamples[i][Sentence.LEFT] = samples[i][Sentence.LEFT]; savedSamples[Sentence.LEFT][i] = samples[Sentence.LEFT][i];
savedSamples[i][Sentence.RIGHT] = samples[i][Sentence.RIGHT]; savedSamples[Sentence.RIGHT][i] = samples[Sentence.RIGHT][i];
} }
if (wetOnly) { if (wetOnly) {
for (int i = 0; i < samples.length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
samples[i][Sentence.LEFT] = 0d; samples[Sentence.LEFT][i] = 0d;
samples[i][Sentence.RIGHT] = 0d; samples[Sentence.RIGHT][i] = 0d;
} }
} }
double[][] subSamples = new double[samples.length][2]; double[][] subSamples = new double[2][samples[Sentence.LEFT].length];
for (int i = 0; i < samples.length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
subSamples[i][Sentence.LEFT] = savedSamples[i][Sentence.LEFT]; subSamples[Sentence.LEFT][i] = savedSamples[Sentence.LEFT][i];
subSamples[i][Sentence.RIGHT] = savedSamples[i][Sentence.RIGHT]; subSamples[Sentence.RIGHT][i] = savedSamples[Sentence.RIGHT][i];
} }
for (DelayLineStore d : delayLines) { for (DelayLineStore d : delayLines) {
for (int i = 0; i < samples.length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
subSamples[i][Sentence.LEFT] = savedSamples[i][Sentence.LEFT]; subSamples[Sentence.LEFT][i] = savedSamples[Sentence.LEFT][i];
subSamples[i][Sentence.RIGHT] = savedSamples[i][Sentence.RIGHT]; subSamples[Sentence.RIGHT][i] = savedSamples[Sentence.RIGHT][i];
} }
d.process(subSamples); 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(); int off = i + d.getSamples();
if ((off < samples.length) && (off > 0)) { if ((off < samples[Sentence.LEFT].length) && (off > 0)) {
samples[Sentence.LEFT][off] = mix(samples[Sentence.LEFT][off], subSamples[Sentence.LEFT][i]);
double[] ns = mix(samples[off], subSamples[i]); samples[Sentence.RIGHT][off] = mix(samples[Sentence.RIGHT][off], subSamples[Sentence.RIGHT][i]);
samples[off][Sentence.LEFT] = ns[Sentence.LEFT];
samples[off][Sentence.RIGHT] = ns[Sentence.RIGHT];
} }
} }
} }
} }
double[] mix(double[] a, double[] b) { double mix(double a, double b) {
double[] out = new double[2]; double out;
if ((a[Sentence.LEFT] < 0) && (b[Sentence.LEFT] < 0)) { if ((a < 0) && (b < 0)) {
out[Sentence.LEFT] = (a[Sentence.LEFT] + b[Sentence.LEFT]) - (a[Sentence.LEFT] * b[Sentence.LEFT]); out = (a + b) - (a * b);
} else if ((a[Sentence.LEFT] > 0) && (b[Sentence.LEFT] > 0)) { } else if ((a > 0) && (b > 0)) {
out[Sentence.LEFT] = (a[Sentence.LEFT] + b[Sentence.LEFT]) - (a[Sentence.LEFT] * b[Sentence.LEFT]); out = (a + b) - (a * b);
} else { } else {
out[Sentence.LEFT] = a[Sentence.LEFT] + b[Sentence.LEFT]; out = a + b;
}
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];
} }
return out; return out;

View File

@@ -29,16 +29,16 @@ public class DelayLineStore {
e.process(samples); e.process(samples);
} }
for (double[] sample : samples) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
sample[Sentence.LEFT] *= gain; samples[Sentence.LEFT][i] *= gain;
sample[Sentence.RIGHT] *= gain; samples[Sentence.RIGHT][i] *= gain;
if (pan < 0) { if (pan < 0) {
double p = 1 + pan; double p = 1 + pan;
sample[Sentence.RIGHT] *= p; samples[Sentence.RIGHT][i] *= p;
} else { } else {
double p = 1 - pan; double p = 1 - pan;
sample[Sentence.LEFT] *= p; samples[Sentence.LEFT][i] *= p;
} }
} }
} }

View File

@@ -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 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 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 disable = new ImageIcon(Icons.class.getResource("icons/disable-effects.png"));
static public final ImageIcon manuscript = new ImageIcon(Icons.class.getResource("icons/manuscript.png"));
} }

View File

@@ -48,7 +48,7 @@ public class LFO implements Effect {
} }
public void process(double[][] samples) { public void process(double[][] samples) {
for (double[] sample : samples) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
double v = 0; double v = 0;
switch (waveform) { switch (waveform) {
case SINE: v = Math.sin(phase); break; case SINE: v = Math.sin(phase); break;
@@ -68,12 +68,12 @@ public class LFO implements Effect {
// Apply it to the sample // Apply it to the sample
switch (mode) { switch (mode) {
case REPLACE: case REPLACE:
sample[Sentence.LEFT] = (sample[Sentence.LEFT] * v); samples[Sentence.LEFT][i] = (samples[Sentence.LEFT][i] * v);
sample[Sentence.RIGHT] = (sample[Sentence.RIGHT] * v); samples[Sentence.RIGHT][i] = (samples[Sentence.RIGHT][i] * v);
break; break;
case ADD: case ADD:
sample[Sentence.LEFT] += (sample[Sentence.LEFT] * v); samples[Sentence.LEFT][i] += (samples[Sentence.LEFT][i] * v);
sample[Sentence.RIGHT] += (sample[Sentence.RIGHT] * v); samples[Sentence.RIGHT][i] += (samples[Sentence.RIGHT][i] * v);
break; break;
} }
} }

View File

@@ -17,6 +17,7 @@ public class MainToolBar extends JToolBar {
JButtonSpacePlay playtoSentence; JButtonSpacePlay playtoSentence;
JButtonSpacePlay stopPlaying; JButtonSpacePlay stopPlaying;
JButtonSpacePlay eq; JButtonSpacePlay eq;
JButtonSpacePlay openManuscript;
JToggleButtonSpacePlay mic; JToggleButtonSpacePlay mic;
JComboBox<String> playbackSpeed; JComboBox<String> playbackSpeed;
@@ -171,6 +172,15 @@ public class MainToolBar extends JToolBar {
playbackSpeed.setSelectedIndex(1); playbackSpeed.setSelectedIndex(1);
add(playbackSpeed); add(playbackSpeed);
addSeparator();
openManuscript = new JButtonSpacePlay(Icons.manuscript, "Open Manuscript", new ActionListener() {
public void actionPerformed(ActionEvent e) {
root.openManuscript();
}
});
add(openManuscript);
setFloatable(false); setFloatable(false);
} }

View File

@@ -34,6 +34,7 @@ public class Options extends JDialog {
JSpinner shortSentenceGap; JSpinner shortSentenceGap;
JSpinner postParagraphGap; JSpinner postParagraphGap;
JSpinner postSectionGap; JSpinner postSectionGap;
JSpinner maxGainVariance;
JTextField ffmpegLocation; JTextField ffmpegLocation;
JComboBox<KVPair> bitRate; JComboBox<KVPair> bitRate;
JComboBox<KVPair> channels; JComboBox<KVPair> channels;
@@ -301,6 +302,7 @@ public class Options extends JDialog {
trimMethod = addDropdown(optionsPanel, "Auto-trim method:", getTrimMethods(), get("audio.recording.trim")); trimMethod = addDropdown(optionsPanel, "Auto-trim method:", getTrimMethods(), get("audio.recording.trim"));
fftThreshold = addSpinner(optionsPanel, "FFT threshold:", 0, 100, 1, getInteger("audio.recording.trim.fft"), ""); 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")); 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); addSeparator(optionsPanel);
@@ -582,6 +584,7 @@ public class Options extends JDialog {
defaultPrefs.put("catenation.post-section", "3000"); defaultPrefs.put("catenation.post-section", "3000");
defaultPrefs.put("audio.recording.trim.fft", "10"); 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.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.archive", (new File(new File(System.getProperty("user.home"), "Recordings"),"archive")).toString());
@@ -718,6 +721,7 @@ public class Options extends JDialog {
set("editor.external", externalEditor.getText()); set("editor.external", externalEditor.getText());
set("cache.size", cacheSize.getValue()); set("cache.size", cacheSize.getValue());
set("audio.recording.trim.fft", fftThreshold.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.recording.trim.blocksize", ((KVPair)fftBlockSize.getSelectedItem()).key);
set("audio.playback.blocksize", ((KVPair)playbackBlockSize.getSelectedItem()).key); set("audio.playback.blocksize", ((KVPair)playbackBlockSize.getSelectedItem()).key);

View File

@@ -20,13 +20,13 @@ public class Pan implements Effect {
} }
public void process(double[][] samples) { public void process(double[][] samples) {
for (double[] sample : samples) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
if (pan < 0) { if (pan < 0) {
double p = 1 + pan; double p = 1 + pan;
sample[Sentence.RIGHT] *= p; samples[Sentence.RIGHT][i] *= p;
} else { } else {
double p = 1 - pan; double p = 1 - pan;
sample[Sentence.LEFT] *= p; samples[Sentence.LEFT][i] *= p;
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,8 @@ import java.util.*;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.text.SimpleDateFormat;
public class Utils { public class Utils {
public static Image getScaledImage(Image srcImg, int w, int h){ public static Image getScaledImage(Image srcImg, int w, int h){
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
@@ -76,4 +78,12 @@ public class Utils {
Runtime.getRuntime().freeMemory() 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;
}
} }

View File

@@ -34,6 +34,8 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
int offsetFactor = 0; int offsetFactor = 0;
int offset = 0; int offset = 0;
String loadedId = null;
ArrayList<MarkerDragListener> markerDragListeners; ArrayList<MarkerDragListener> markerDragListeners;
public Waveform() { public Waveform() {
@@ -79,7 +81,7 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
if (samples != null) { if (samples != null) {
int num = samples.length; int num = samples[Sentence.LEFT].length;
step = num / zoomFactor / w; step = num / zoomFactor / w;
if (step == 0) return; if (step == 0) return;
@@ -97,8 +99,8 @@ 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++) {
if (offset + (n * step) + o >= samples.length) break; if (offset + (n * step) + o >= samples[Sentence.LEFT].length) break;
double sample = (samples[offset + (n * step) + o][Sentence.LEFT] + samples[offset + (n * step) + o][Sentence.RIGHT]) / 2d; double sample = (samples[Sentence.LEFT][offset + (n * step) + o] + samples[Sentence.RIGHT][offset + (n * step) + o]) / 2d;
if (sample >= 0) { if (sample >= 0) {
have += sample; have += sample;
hcnt++; hcnt++;
@@ -387,4 +389,12 @@ public class Waveform extends JPanel implements MouseListener, MouseMotionListen
public int getCutEnd() { public int getCutEnd() {
return cutExit; return cutExit;
} }
public void setId(String id) {
loadedId = id;
}
public String getId() {
return loadedId;
}
} }