Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 90ca84cfbf | |||
| a18ca1ce21 | |||
| b92babb5cd | |||
| e3231ec495 | |||
| 4896ee7a65 | |||
| ce3eb7165a | |||
| 4de00b8fac | |||
| ebe777bdc5 | |||
| 3b5cacb8ad | |||
| db7d297dbc | |||
| 2f9abf7629 | |||
| b6063d2fed | |||
| e1f566f0c8 | |||
| 9fa892a6fd | |||
| 1572e163ef | |||
| 2791691057 | |||
| 575537ae66 |
@@ -1 +1 @@
|
|||||||
version=0.2.2
|
version=0.3.4
|
||||||
|
|||||||
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 |
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,20 @@ import java.nio.file.*;
|
|||||||
import javax.swing.tree.*;
|
import javax.swing.tree.*;
|
||||||
import javax.sound.sampled.*;
|
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 {
|
public class Book extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
@@ -17,6 +31,9 @@ public class Book extends DefaultMutableTreeNode {
|
|||||||
String genre;
|
String genre;
|
||||||
String comment;
|
String comment;
|
||||||
String ACX;
|
String ACX;
|
||||||
|
String manuscript;
|
||||||
|
|
||||||
|
String defaultEffect = "none";
|
||||||
|
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
int channels;
|
int channels;
|
||||||
@@ -31,7 +48,64 @@ public class Book extends DefaultMutableTreeNode {
|
|||||||
|
|
||||||
prefs = p;
|
prefs = p;
|
||||||
name = bookname;
|
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; }
|
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) {
|
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()) {
|
||||||
@@ -216,4 +294,108 @@ public class Book extends DefaultMutableTreeNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.util.*;
|
||||||
import java.io.*;
|
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 {
|
public class BookPanel extends JPanel {
|
||||||
String name;
|
String name;
|
||||||
String author;
|
String author;
|
||||||
@@ -25,6 +39,7 @@ public class BookPanel extends JPanel {
|
|||||||
JPanel panel;
|
JPanel panel;
|
||||||
|
|
||||||
File root;
|
File root;
|
||||||
|
File configFile;
|
||||||
|
|
||||||
boolean highlight = false;
|
boolean highlight = false;
|
||||||
|
|
||||||
@@ -36,13 +51,78 @@ public class BookPanel extends JPanel {
|
|||||||
try {
|
try {
|
||||||
root = r;
|
root = r;
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.loadFromXML(new FileInputStream(new File(root, "audiobook.abk")));
|
|
||||||
|
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);
|
loadBookData(props, null);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
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) {
|
public void loadBookData(Properties props, ImageIcon i) {
|
||||||
try {
|
try {
|
||||||
name = props.getProperty("book.name");
|
name = props.getProperty("book.name");
|
||||||
@@ -71,7 +151,12 @@ public class BookPanel extends JPanel {
|
|||||||
resizedCover = Utils.getScaledImage(cover.getImage(), 75, 75);
|
resizedCover = Utils.getScaledImage(cover.getImage(), 75, 75);
|
||||||
iconLabel = new JLabel(new ImageIcon(resizedCover));
|
iconLabel = new JLabel(new ImageIcon(resizedCover));
|
||||||
}
|
}
|
||||||
|
populate();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void populate() {
|
||||||
iconLabel.setSize(new Dimension(75, 75));
|
iconLabel.setSize(new Dimension(75, 75));
|
||||||
iconLabel.setPreferredSize(new Dimension(75, 75));
|
iconLabel.setPreferredSize(new Dimension(75, 75));
|
||||||
|
|
||||||
@@ -100,12 +185,10 @@ public class BookPanel extends JPanel {
|
|||||||
panel.setOpaque(true);
|
panel.setOpaque(true);
|
||||||
setBackground(new Color(0x20, 0x20, 0x20));
|
setBackground(new Color(0x20, 0x20, 0x20));
|
||||||
setOpaque(true);
|
setOpaque(true);
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getConfigFile() {
|
public File getConfigFile() {
|
||||||
return new File(root, "audiobook.abk");
|
return configFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void highlight() {
|
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) {
|
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,72 @@ 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 = 0.1d;
|
||||||
|
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.weightx = 0.0d;
|
||||||
|
ctx.gridx = 2;
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,21 @@ import it.sauronsoftware.jave.*;
|
|||||||
import com.mpatric.mp3agic.*;
|
import com.mpatric.mp3agic.*;
|
||||||
import javax.sound.sampled.*;
|
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 name;
|
||||||
String id;
|
String id;
|
||||||
@@ -21,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);
|
||||||
|
|
||||||
@@ -28,7 +43,25 @@ public class Chapter extends DefaultMutableTreeNode {
|
|||||||
name = chaptername;
|
name = chaptername;
|
||||||
preGap = Options.getInteger("catenation.pre-chapter");
|
preGap = Options.getInteger("catenation.pre-chapter");
|
||||||
postGap = Options.getInteger("catenation.post-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() {
|
public String getId() {
|
||||||
@@ -249,4 +282,50 @@ public class Chapter extends DefaultMutableTreeNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,10 +86,16 @@ public class OpenBookPanel extends JPanel {
|
|||||||
for (File b : dir.listFiles()) {
|
for (File b : dir.listFiles()) {
|
||||||
if (b == null) continue;
|
if (b == null) continue;
|
||||||
if (!b.isDirectory()) continue;
|
if (!b.isDirectory()) continue;
|
||||||
File xml = new File(b, "audiobook.abk");
|
File xml = new File(b, "audiobook.abx");
|
||||||
if (xml.exists()) {
|
if (xml.exists()) {
|
||||||
BookPanel book = new BookPanel(b);
|
BookPanel book = new BookPanel(b);
|
||||||
model.addBook(book);
|
model.addBook(book);
|
||||||
|
} else {
|
||||||
|
xml = new File(b, "audiobook.abk");
|
||||||
|
if (xml.exists()) {
|
||||||
|
BookPanel book = new BookPanel(b);
|
||||||
|
model.addBook(book);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,23 @@ import org.json.*;
|
|||||||
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
|
|
||||||
|
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.Text;
|
||||||
|
|
||||||
public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
public class Sentence extends BookTreeNode implements Cacheable {
|
||||||
|
|
||||||
String text;
|
String text;
|
||||||
String id;
|
String id;
|
||||||
|
String notes;
|
||||||
int postGap;
|
int postGap;
|
||||||
int startOffset = 0;
|
int startOffset = 0;
|
||||||
int endOffset = 0;
|
int endOffset = 0;
|
||||||
@@ -49,6 +61,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
boolean inSample;
|
boolean inSample;
|
||||||
boolean attention = false;
|
boolean attention = false;
|
||||||
|
boolean processed = false;
|
||||||
|
|
||||||
String effectChain = null;
|
String effectChain = null;
|
||||||
|
|
||||||
@@ -65,7 +78,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
TargetDataLine line;
|
TargetDataLine line;
|
||||||
AudioInputStream inputStream;
|
AudioInputStream inputStream;
|
||||||
AudioFormat storedFormat = null;
|
AudioFormat storedFormat = null;
|
||||||
double storedLength = -1d;
|
|
||||||
|
double runtime = -1d;
|
||||||
|
|
||||||
double[][] audioData = null;
|
double[][] audioData = null;
|
||||||
|
|
||||||
@@ -75,20 +89,26 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
boolean effectEthereal = false;
|
boolean effectEthereal = false;
|
||||||
|
|
||||||
|
public void setSampleSize(int s) {
|
||||||
|
sampleSize = s;
|
||||||
|
}
|
||||||
|
|
||||||
static class RecordingThread implements Runnable {
|
static class RecordingThread implements Runnable {
|
||||||
|
|
||||||
boolean running = false;
|
boolean running = false;
|
||||||
boolean recording = false;
|
boolean recording = false;
|
||||||
|
Sentence sent = null;
|
||||||
|
|
||||||
File tempFile;
|
File tempFile;
|
||||||
File wavFile;
|
File wavFile;
|
||||||
|
|
||||||
AudioFormat format;
|
AudioFormat format;
|
||||||
|
|
||||||
public RecordingThread(File tf, File wf, AudioFormat af) {
|
public RecordingThread(File tf, File wf, AudioFormat af, Sentence s) {
|
||||||
tempFile = tf;
|
tempFile = tf;
|
||||||
wavFile = wf;
|
wavFile = wf;
|
||||||
format = af;
|
format = af;
|
||||||
|
sent = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -110,6 +130,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
fos.write(buf, 0, nr);
|
fos.write(buf, 0, nr);
|
||||||
fos.close();
|
fos.close();
|
||||||
|
|
||||||
|
sent.setSampleSize(len / format.getFrameSize());
|
||||||
|
|
||||||
FileInputStream fis = new FileInputStream(tempFile);
|
FileInputStream fis = new FileInputStream(tempFile);
|
||||||
AudioInputStream ais = new AudioInputStream(fis, format, len / format.getFrameSize());
|
AudioInputStream ais = new AudioInputStream(fis, format, len / format.getFrameSize());
|
||||||
fos = new FileOutputStream(wavFile);
|
fos = new FileOutputStream(wavFile);
|
||||||
@@ -155,6 +177,34 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
postGap = Options.getInteger("catenation.post-sentence");
|
postGap = Options.getInteger("catenation.post-sentence");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Sentence(Element root) {
|
||||||
|
super("");
|
||||||
|
id = root.getAttribute("id");
|
||||||
|
text = Book.getTextNode(root, "text");
|
||||||
|
notes = Book.getTextNode(root, "notes");
|
||||||
|
setUserObject(text);
|
||||||
|
setPostGap(Utils.s2i(Book.getTextNode(root, "post-gap")));
|
||||||
|
setStartOffset(Utils.s2i(Book.getTextNode(root, "start-offset")));
|
||||||
|
setEndOffset(Utils.s2i(Book.getTextNode(root, "end-offset")));
|
||||||
|
crossStartOffset = Utils.s2i(Book.getTextNode(root, "cross-start-offset", "-1"));
|
||||||
|
crossEndOffset = Utils.s2i(Book.getTextNode(root, "end-offset", "-1"));
|
||||||
|
setLocked(Utils.s2b(Book.getTextNode(root, "locked")));
|
||||||
|
setAttentionFlag(Utils.s2b(Book.getTextNode(root, "attention")));
|
||||||
|
setGain(Utils.s2d(Book.getTextNode(root, "gain")));
|
||||||
|
setEffectChain(Book.getTextNode(root, "effect"));
|
||||||
|
setPostGapType(Book.getTextNode(root, "gaptype"));
|
||||||
|
sampleSize = Utils.s2i(Book.getTextNode(root, "samples"));
|
||||||
|
processed = Utils.s2b(Book.getTextNode(root, "processed"));
|
||||||
|
runtime = Utils.s2d(Book.getTextNode(root, "time", "-1.000"));
|
||||||
|
|
||||||
|
if ((crossStartOffset == -1) || (crossEndOffset == -1)) {
|
||||||
|
System.err.println("Updating " + id);
|
||||||
|
updateCrossings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime <= 0.01d) getLength();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean startRecording() {
|
public boolean startRecording() {
|
||||||
if (AudiobookRecorder.window.microphone == null) {
|
if (AudiobookRecorder.window.microphone == null) {
|
||||||
JOptionPane.showMessageDialog(AudiobookRecorder.window, "Microphone not started. Start the microphone first.", "Error", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(AudiobookRecorder.window, "Microphone not started. Start the microphone first.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
@@ -163,7 +213,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
CacheManager.removeFromCache(this);
|
CacheManager.removeFromCache(this);
|
||||||
|
|
||||||
recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat());
|
recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat(), this);
|
||||||
|
|
||||||
Thread rc = new Thread(recordingThread);
|
Thread rc = new Thread(recordingThread);
|
||||||
rc.setDaemon(true);
|
rc.setDaemon(true);
|
||||||
@@ -203,6 +253,12 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
autoTrimSamplePeak(useRaw);
|
autoTrimSamplePeak(useRaw);
|
||||||
} else if (tm.equals("fft")) {
|
} else if (tm.equals("fft")) {
|
||||||
autoTrimSampleFFT(useRaw);
|
autoTrimSampleFFT(useRaw);
|
||||||
|
} else {
|
||||||
|
startOffset = 0;
|
||||||
|
crossStartOffset = 0;
|
||||||
|
endOffset = sampleSize - 1;
|
||||||
|
crossEndOffset = sampleSize - 1;
|
||||||
|
processed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +360,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
updateCrossings(useRaw);
|
updateCrossings(useRaw);
|
||||||
intens = null;
|
intens = null;
|
||||||
samples = null;
|
samples = null;
|
||||||
|
processed = true;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void autoTrimSamplePeak() {
|
public void autoTrimSamplePeak() {
|
||||||
@@ -360,6 +417,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
if (startOffset < 0) startOffset = 0;
|
if (startOffset < 0) startOffset = 0;
|
||||||
if (endOffset >= samples.length) endOffset = samples.length-1;
|
if (endOffset >= samples.length) endOffset = samples.length-1;
|
||||||
updateCrossings(useRaw);
|
updateCrossings(useRaw);
|
||||||
|
processed = true;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@@ -369,6 +428,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public void setText(String t) {
|
public void setText(String t) {
|
||||||
overrideText = null;
|
overrideText = null;
|
||||||
text = t;
|
text = t;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
@@ -401,11 +461,14 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
return text;
|
||||||
|
/*
|
||||||
if (effectChain == null) return text;
|
if (effectChain == null) return text;
|
||||||
if (effectChain.equals("none")) return text;
|
if (effectChain.equals("none")) return text;
|
||||||
Effect e = AudiobookRecorder.window.effects.get(effectChain);
|
Effect e = AudiobookRecorder.window.effects.get(effectChain);
|
||||||
if (e == null) return text;
|
if (e == null) return text;
|
||||||
return text + " (" + e.toString() + ")";
|
return text + " (" + e.toString() + ")";
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRecording() {
|
public boolean isRecording() {
|
||||||
@@ -416,6 +479,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
if (o instanceof String) {
|
if (o instanceof String) {
|
||||||
String so = (String)o;
|
String so = (String)o;
|
||||||
text = so;
|
text = so;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,6 +513,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public void updateCrossings(boolean useRaw) {
|
public void updateCrossings(boolean useRaw) {
|
||||||
updateStartCrossing(useRaw);
|
updateStartCrossing(useRaw);
|
||||||
updateEndCrossing(useRaw);
|
updateEndCrossing(useRaw);
|
||||||
|
runtime = -1d;
|
||||||
|
getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateStartCrossing() {
|
public void updateStartCrossing() {
|
||||||
@@ -475,6 +541,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
if (startOffset != o) {
|
if (startOffset != o) {
|
||||||
startOffset = o;
|
startOffset = o;
|
||||||
crossStartOffset = -1;
|
crossStartOffset = -1;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,9 +557,18 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
if (endOffset != o) {
|
if (endOffset != o) {
|
||||||
endOffset = o;
|
endOffset = o;
|
||||||
crossEndOffset = -1;
|
crossEndOffset = -1;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStartCrossing(int o) {
|
||||||
|
crossStartOffset = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndCrossing(int o) {
|
||||||
|
crossEndOffset = o;
|
||||||
|
}
|
||||||
|
|
||||||
public int getSampleSize() {
|
public int getSampleSize() {
|
||||||
if (sampleSize == -1) {
|
if (sampleSize == -1) {
|
||||||
loadFile();
|
loadFile();
|
||||||
@@ -518,7 +594,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public void doRecognition(StreamSpeechRecognizer recognizer) {
|
public void doRecognition(StreamSpeechRecognizer recognizer) {
|
||||||
try {
|
try {
|
||||||
setText("[recognising...]");
|
setText("[recognising...]");
|
||||||
AudiobookRecorder.window.bookTreeModel.reload(this);
|
reloadTree();
|
||||||
|
|
||||||
byte[] inData = getPCMData();
|
byte[] inData = getPCMData();
|
||||||
|
|
||||||
@@ -533,7 +609,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
recognizer.stopRecognition();
|
recognizer.stopRecognition();
|
||||||
|
|
||||||
setText(res);
|
setText(res);
|
||||||
AudiobookRecorder.window.bookTreeModel.reload(this);
|
reloadTree();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -569,7 +645,9 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setLocked(boolean l) {
|
public void setLocked(boolean l) {
|
||||||
|
if (locked == l) return;
|
||||||
locked = l;
|
locked = l;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLocked() {
|
public boolean isLocked() {
|
||||||
@@ -588,7 +666,6 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
audioData = null;
|
audioData = null;
|
||||||
processedAudio = null;
|
processedAudio = null;
|
||||||
storedFormat = null;
|
storedFormat = null;
|
||||||
storedLength = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean lockedInCache() {
|
public boolean lockedInCache() {
|
||||||
@@ -644,13 +721,16 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
/* Get the length of the sample in seconds */
|
/* Get the length of the sample in seconds */
|
||||||
public double getLength() {
|
public double getLength() {
|
||||||
if (storedLength > -1d) return storedLength;
|
if (runtime > 0.01d) return runtime;
|
||||||
|
File f = getFile();
|
||||||
|
if (!f.exists()) { // Not recorded yet!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
AudioFormat format = getAudioFormat();
|
AudioFormat format = getAudioFormat();
|
||||||
float sampleFrequency = format.getFrameRate();
|
float sampleFrequency = format.getFrameRate();
|
||||||
int length = crossEndOffset - crossStartOffset;
|
int length = crossEndOffset - crossStartOffset;
|
||||||
double time = (double)length / (double)sampleFrequency;
|
runtime = (double)length / (double)sampleFrequency;
|
||||||
storedLength = time;
|
return runtime;
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sentence cloneSentence() throws IOException {
|
public Sentence cloneSentence() throws IOException {
|
||||||
@@ -661,17 +741,21 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
sentence.setStartOffset(getStartOffset());
|
sentence.setStartOffset(getStartOffset());
|
||||||
sentence.setEndOffset(getEndOffset());
|
sentence.setEndOffset(getEndOffset());
|
||||||
|
sentence.setStartCrossing(getStartCrossing());
|
||||||
|
sentence.setEndCrossing(getEndCrossing());
|
||||||
|
|
||||||
File from = getFile();
|
File from = getFile();
|
||||||
File to = sentence.getFile();
|
File to = sentence.getFile();
|
||||||
Files.copy(from.toPath(), to.toPath());
|
Files.copy(from.toPath(), to.toPath());
|
||||||
|
|
||||||
sentence.updateCrossings();
|
// sentence.updateCrossings();
|
||||||
return sentence;
|
return sentence;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAttentionFlag(boolean f) {
|
public void setAttentionFlag(boolean f) {
|
||||||
|
if (attention == f) return;
|
||||||
attention = f;
|
attention = f;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getAttentionFlag() {
|
public boolean getAttentionFlag() {
|
||||||
@@ -679,17 +763,21 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public double getPeakValue() {
|
public double getPeakValue() {
|
||||||
return getPeakValue(false);
|
return getPeakValue(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getPeakValue(boolean useRaw) {
|
public double getPeakValue(boolean useRaw) {
|
||||||
|
return getPeakValue(useRaw, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPeakValue(boolean useRaw, boolean applyGain) {
|
||||||
double oldGain = gain;
|
double oldGain = gain;
|
||||||
gain = 1.0d;
|
gain = 1.0d;
|
||||||
double[][] samples = null;
|
double[][] samples = null;
|
||||||
if (useRaw) {
|
if (useRaw) {
|
||||||
samples = getRawAudioData();
|
samples = getRawAudioData();
|
||||||
} else {
|
} else {
|
||||||
samples = getProcessedAudioData();
|
samples = getProcessedAudioData(true, applyGain);
|
||||||
}
|
}
|
||||||
gain = oldGain;
|
gain = oldGain;
|
||||||
if (samples == null) {
|
if (samples == null) {
|
||||||
@@ -729,12 +817,24 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
return gain;
|
return gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void normalize() {
|
public double normalize(double low, double high) {
|
||||||
if (locked) return;
|
if (locked) return gain;
|
||||||
double max = getPeakValue();
|
double max = getPeakValue(true, false);
|
||||||
|
double d = 0.708 / max;
|
||||||
|
if (d > 1d) d = 1d;
|
||||||
|
if (d < low) d = low;
|
||||||
|
if (d > high) d = high;
|
||||||
|
setGain(d);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double normalize() {
|
||||||
|
if (locked) return gain;
|
||||||
|
double max = getPeakValue(true, false);
|
||||||
double d = 0.708 / max;
|
double d = 0.708 / max;
|
||||||
if (d > 1d) d = 1d;
|
if (d > 1d) d = 1d;
|
||||||
setGain(d);
|
setGain(d);
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExternalEditor implements Runnable {
|
class ExternalEditor implements Runnable {
|
||||||
@@ -1155,10 +1255,14 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized public double[][] getProcessedAudioData() {
|
synchronized public double[][] getProcessedAudioData() {
|
||||||
return getProcessedAudioData(true);
|
return getProcessedAudioData(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized public double[][] getProcessedAudioData(boolean effectsEnabled) {
|
synchronized public double[][] getProcessedAudioData(boolean effectsEnabled) {
|
||||||
|
return getProcessedAudioData(effectsEnabled, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public double[][] getProcessedAudioData(boolean effectsEnabled, boolean applyGain) {
|
||||||
loadFile();
|
loadFile();
|
||||||
if (processedAudio != null) {
|
if (processedAudio != null) {
|
||||||
return processedAudio;
|
return processedAudio;
|
||||||
@@ -1194,13 +1298,13 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (applyGain) {
|
||||||
// Add final master gain stage
|
// Add final master gain stage
|
||||||
for (int i = 0; i < processedAudio.length; i++) {
|
for (int i = 0; i < processedAudio.length; i++) {
|
||||||
processedAudio[i][LEFT] *= gain;
|
processedAudio[i][LEFT] *= gain;
|
||||||
processedAudio[i][RIGHT] *= gain;
|
processedAudio[i][RIGHT] *= gain;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return processedAudio;
|
return processedAudio;
|
||||||
}
|
}
|
||||||
@@ -1259,10 +1363,14 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setEffectChain(String key) {
|
public void setEffectChain(String key) {
|
||||||
|
if ((effectChain != null) && (effectChain.equals(key))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ((effectChain != null) && (!effectChain.equals(key))) {
|
if ((effectChain != null) && (!effectChain.equals(key))) {
|
||||||
CacheManager.removeFromCache(this);
|
CacheManager.removeFromCache(this);
|
||||||
}
|
}
|
||||||
effectChain = key;
|
effectChain = key;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEffectChain() {
|
public String getEffectChain() {
|
||||||
@@ -1289,6 +1397,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
postGapType = t;
|
postGapType = t;
|
||||||
|
reloadTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetPostGap() {
|
public void resetPostGap() {
|
||||||
@@ -1325,6 +1434,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
out.put("gain", String.format("%.8f", getGain()));
|
out.put("gain", String.format("%.8f", getGain()));
|
||||||
out.put("effect", getEffectChain());
|
out.put("effect", getEffectChain());
|
||||||
out.put("gaptype", getPostGapType());
|
out.put("gaptype", getPostGapType());
|
||||||
|
// out.put("samples", Integer.toString(getSampleSize()));
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -1341,4 +1451,53 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Element getSentenceXML(Document doc) {
|
||||||
|
Element sentenceNode = doc.createElement("sentence");
|
||||||
|
sentenceNode.setAttribute("id", getId());
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "text", getText()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "post-gap", getPostGap()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "start-offset", getStartOffset()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "end-offset", getEndOffset()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "cross-start-offset", crossStartOffset));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "cross-end-offset", crossEndOffset));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "locked", isLocked()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "attention", getAttentionFlag()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "gain", getGain()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "effect", getEffectChain()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "gaptype", getPostGapType()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "samples", getSampleSize()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "processed", isProcessed()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "notes", getNotes()));
|
||||||
|
sentenceNode.appendChild(Book.makeTextNode(doc, "time", getLength()));
|
||||||
|
return sentenceNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isProcessed() {
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProcessed(boolean p) {
|
||||||
|
processed = p;
|
||||||
|
reloadTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotes(String n) {
|
||||||
|
notes = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotes() {
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSelect() {
|
||||||
|
AudiobookRecorder.window.setSentenceNotes(notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reloadTree() {
|
||||||
|
if (id.equals("room-noise")) return;
|
||||||
|
if (getParent() == null) return;
|
||||||
|
AudiobookRecorder.window.bookTreeModel.reload(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user