Implemented export profiles

This commit is contained in:
2024-04-06 21:21:23 +01:00
parent 81d436dcf5
commit c12187cae9
8 changed files with 312 additions and 140 deletions

View File

@@ -0,0 +1,21 @@
<profile>
<code>librivox</code>
<name>LibriVox.org</name>
<export>
<bitrate>128000</bitrate>
<channels>1</channels>
<samples>44100</samples>
<format>{chapter.name:lower}_{book.author.short:lower}_{narrator.initials:lower}_{file.bitrate.kb}kb</format>
</export>
<gaps>
<pre-chapter>500</pre-chapter>
<post-chapter>5000</post-chapter>
<post-sentence>400</post-sentence>
<followon>100</followon>
<post-paragraph>1000</post-paragraph>
<post-section>1200</post-section>
</gaps>
<audio>
<rms>-19</rms>
</audio>
</profile>

View File

@@ -6,6 +6,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ArrayDeque;
import java.util.Enumeration;
import java.util.Properties;
@@ -119,6 +120,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public static CommandLine CLI = new CommandLine();
public static HashMap<String, ExportProfile> exportProfiles = new HashMap<String, ExportProfile>();
MainToolBar toolBar;
JMenuBar menuBar;
@@ -357,6 +360,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Options.loadPreferences();
loadExportProfiles();
queueMonitor = new QueueMonitor(processQueue);
for (int i = 0; i < Options.getInteger("process.threads"); i++) {
@@ -1079,7 +1084,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public void createNewBook() {
Debug.trace();
BookInfoPanel info = new BookInfoPanel("", "", "", "", "", "");
BookInfoPanel info = new BookInfoPanel("", "", "", "", "", "", "", "", "");
int r = JOptionPane.showConfirmDialog(this, info, "New Book", JOptionPane.OK_CANCEL_OPTION);
if (r != JOptionPane.OK_OPTION) return;
@@ -1634,10 +1639,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
}
});
JMenu exportChapter = new JMenu("Export chapter...");
JMenuObject exportChapterACX = new JMenuObject("For ACX", c, new ActionListener() {
JMenuObject exportChapter = new JMenuObject("Export Chapter", c, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject o = (JMenuObject)e.getSource();
@@ -1645,37 +1647,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
ProgressDialog ed = new ProgressDialog("Exporting " + chap.getName());
ExportThread t = new ExportThread(chap, ed, "{book.title} - {chapter.number}");
Thread nt = new Thread(t);
nt.start();
ed.setVisible(true);
}
});
JMenuObject exportChapterABU = new JMenuObject("For Audiobooks Unleashed", c, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject o = (JMenuObject)e.getSource();
Chapter chap = (Chapter)o.getObject();
ProgressDialog ed = new ProgressDialog("Exporting " + chap.getName());
ExportThread t = new ExportThread(chap, ed, "{book.isbn}_{chapter.number}");
Thread nt = new Thread(t);
nt.start();
ed.setVisible(true);
}
});
JMenuObject exportChapterLibri = new JMenuObject("For LibriVox.org", c, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject o = (JMenuObject)e.getSource();
Chapter chap = (Chapter)o.getObject();
ProgressDialog ed = new ProgressDialog("Exporting " + chap.getName());
ExportThread t = new ExportThread(chap, ed, "{chapter.name:lower}_{book.author:lower}_{narrator.initials:lower}_{file.bitrate.kb}kb");
ExportThread t = new ExportThread(chap, ed);
Thread nt = new Thread(t);
nt.start();
ed.setVisible(true);
@@ -1785,9 +1757,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
menu.addSeparator();
menu.add(importWav);
menu.add(exportChapter);
exportChapter.add(exportChapterACX);
exportChapter.add(exportChapterABU);
exportChapter.add(exportChapterLibri);
menu.addSeparator();
menu.add(deleteChapter);
menu.addSeparator();
@@ -1841,35 +1810,16 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
menu.addSeparator();
JMenu exportAll = new JMenu("Export All Audio...");
menu.add(exportAll);
exportAll.add(new JMenuObject("For ACX", book, new ActionListener() {
JMenuObject exportAll = new JMenuObject("Export Book", book, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject src = (JMenuObject)(e.getSource());
Book thisBook = (Book)(src.getObject());
exportAudio(thisBook, "{book.title} - {chapter.number}");
exportAudio(thisBook);
}
}));
});
exportAll.add(new JMenuObject("For Audiobooks Unleashed", book, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject src = (JMenuObject)(e.getSource());
Book thisBook = (Book)(src.getObject());
exportAudio(thisBook, "{book.isbn}_{chapter.number}");
}
}));
exportAll.add(new JMenuObject("For LibriVox.org", book, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject src = (JMenuObject)(e.getSource());
Book thisBook = (Book)(src.getObject());
exportAudio(thisBook, "{chapter.name:lower}_{book.author:lower}_{narrator.initials:lower}_{file.bitrate.kb}kb");
}
}));
menu.add(exportAll);
JMenu visitACX = new JMenu("Visit ACX");
@@ -2335,8 +2285,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public Chapter convertChapter(String name, String id, Properties data) {
Chapter c = new Chapter(id, data.getProperty("chapter." + name + ".name"));
c.setPostGap(Utils.s2i(data.getProperty("chapter." + name + ".post-gap")));
c.setPreGap(Utils.s2i(data.getProperty("chapter." + name + ".pre-gap")));
for (int i = 0; i < 100000000; i++) {
String sid = data.getProperty(String.format("chapter." + name + ".sentence.%08d.id", i));
@@ -2517,14 +2465,12 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
class ExportThread implements Runnable {
ProgressDialog exportDialog;
Chapter chapter;
String format;
public ExportThread(Chapter c, ProgressDialog e, String f) {
public ExportThread(Chapter c, ProgressDialog e) {
super();
Debug.trace();
exportDialog = e;
chapter = c;
format = f;
}
@SuppressWarnings("unchecked")
@@ -2532,7 +2478,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace();
try {
chapter.exportChapter(exportDialog, format);
chapter.exportChapter(exportDialog);
} catch (Exception e) {
e.printStackTrace();
}
@@ -2542,7 +2488,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
}
@SuppressWarnings("unchecked")
public void exportAudio(Book book, String format) {
public void exportAudio(Book book) {
Debug.trace();
for (Enumeration o = book.children(); o.hasMoreElements();) {
@@ -2550,7 +2496,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
if (c.getChildCount() == 0) continue;
ProgressDialog ed = new ProgressDialog("Exporting " + c.getName());
ExportThread t = new ExportThread(c, ed, format);
ExportThread t = new ExportThread(c, ed);
Thread nt = new Thread(t);
nt.start();
ed.setVisible(true);
@@ -3601,13 +3547,21 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public void editBookInfo(Book book) {
JTabbedPane tabs = new JTabbedPane();
String epc = "";
if (book.getExportProfile() != null) {
epc = book.getExportProfile().getCode();
}
BookInfoPanel info = new BookInfoPanel(
book.getName(),
book.getShortTitle(),
book.getAuthor(),
book.getShortAuthor(),
book.getGenre(),
book.getComment(),
book.getACX(),
book.getISBN()
book.getISBN(),
epc
);
tabs.add("Data", info);
@@ -3644,7 +3598,9 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
if (r != JOptionPane.OK_OPTION) return;
String tit = info.getTitle();
String stit = info.getShortTitle();
String aut = info.getAuthor();
String saut = info.getShortAuthor();
String gen = info.getGenre();
String com = info.getComment();
String acx = info.getACX();
@@ -3656,11 +3612,14 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
book.setDefaultEffect(de.getKey());
}
book.setTitle(tit);
book.setShortTitle(stit);
book.setAuthor(aut);
book.setShortAuthor(saut);
book.setGenre(gen);
book.setComment(com);
book.setACX(acx);
book.setISBN(isbn);
book.setExportProfile(info.getExportProfile());
// if (!(book().getName().equals(tit))) {
// book().renameBook(tit);
// }
@@ -3708,4 +3667,21 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
ex.printStackTrace();
}
}
public void loadExportProfiles() {
exportProfiles.clear();
ExportProfile dp = new ExportProfile();
exportProfiles.put(dp.getCode(), dp);
File system = new File(Options.get("path.storage"), "system");
if (system.exists() && system.isDirectory()) {
File profiles = new File(system, "profiles");
for (File f : profiles.listFiles()) {
if (f.getName().endsWith(".abprof")) {
ExportProfile p = new ExportProfile(f);
exportProfiles.put(p.getCode(), p);
}
}
}
}
}

View File

@@ -39,7 +39,9 @@ import org.xml.sax.SAXException;
public class Book extends BookTreeNode {
String name;
String shortName;
String author;
String shortAuthor;
String genre;
String comment;
String ACX;
@@ -53,6 +55,7 @@ public class Book extends BookTreeNode {
Random rng = new Random();
TreeMap<String, EffectGroup> effects;
AudioFormat cachedFormat = null;
ExportProfile exportProfile;
public Book(String bookname) {
super(bookname);
@@ -78,13 +81,16 @@ public class Book extends BookTreeNode {
Element root = doc.getDocumentElement();
name = getTextNode(root, "title");
shortName = getTextNode(root, "shorttitle");
author = getTextNode(root, "author");
shortAuthor = getTextNode(root, "shortauthor");
genre = getTextNode(root, "genre");
comment = getTextNode(root, "comment");
ACX = getTextNode(root, "acx");
ISBN = getTextNode(root, "isbn");
manuscript = getTextNode(root, "manuscript");
notes = getTextNode(root, "notes");
exportProfile = AudiobookRecorder.exportProfiles.get(getTextNode(root, "exportprofile"));
Element settings = getNode(root, "settings");
Element audioSettings = getNode(settings, "audio");
@@ -131,13 +137,16 @@ public class Book extends BookTreeNode {
public void loadBookXML(Element root, DefaultTreeModel model) {
Debug.trace();
name = getTextNode(root, "title");
shortName = getTextNode(root, "shorttitle");
author = getTextNode(root, "author");
shortAuthor = getTextNode(root, "shortauthor");
genre = getTextNode(root, "genre");
comment = getTextNode(root, "comment");
ACX = getTextNode(root, "acx");
ISBN = getTextNode(root, "isbn");
manuscript = getTextNode(root, "manuscript");
notes = getTextNode(root, "notes");
exportProfile = AudiobookRecorder.exportProfiles.get(getTextNode(root, "exportprofile"));
Element settings = getNode(root, "settings");
Element audioSettings = getNode(settings, "audio");
@@ -182,14 +191,18 @@ public class Book extends BookTreeNode {
}
public void setTitle(String n) { Debug.trace(); name = n; }
public void setShortTitle(String n) { Debug.trace(); shortName = n; }
public void setAuthor(String a) { Debug.trace(); author = a; }
public void setShortAuthor(String a) { Debug.trace(); shortAuthor = a; }
public void setGenre(String g) { Debug.trace(); genre = g; }
public void setComment(String c) { Debug.trace(); comment = c; }
public void setACX(String c) { Debug.trace(); ACX = c; }
public void setISBN(String c) { Debug.trace(); ISBN = c; }
public String getTitle() { Debug.trace(); return name; }
public String getShortTitle() { Debug.trace(); return shortName; }
public String getAuthor() { Debug.trace(); return author; }
public String getShortAuthor() { Debug.trace(); return shortAuthor; }
public String getGenre() { Debug.trace(); return genre; }
public String getComment() { Debug.trace(); return comment; }
public String getACX() { Debug.trace(); if (ACX == null) return ""; return ACX; }
@@ -379,6 +392,8 @@ public class Book extends BookTreeNode {
doc.appendChild(root);
root.appendChild(makeTextNode(doc, "title", name));
root.appendChild(makeTextNode(doc, "shortauthor", shortAuthor));
root.appendChild(makeTextNode(doc, "shorttitle", shortName));
root.appendChild(makeTextNode(doc, "author", author));
root.appendChild(makeTextNode(doc, "comment", comment));
root.appendChild(makeTextNode(doc, "genre", genre));
@@ -386,6 +401,9 @@ public class Book extends BookTreeNode {
root.appendChild(makeTextNode(doc, "isbn", ISBN));
root.appendChild(makeTextNode(doc, "manuscript", manuscript));
root.appendChild(makeTextNode(doc, "notes", notes));
if (exportProfile != null) {
root.appendChild(makeTextNode(doc, "exportprofile", exportProfile.getCode()));
}
Element settingsNode = doc.createElement("settings");
root.appendChild(settingsNode);
@@ -698,4 +716,15 @@ public class Book extends BookTreeNode {
return len;
}
public ExportProfile getExportProfile() {
if (exportProfile == null) {
return AudiobookRecorder.exportProfiles.get("librivox");
}
return exportProfile;
}
public void setExportProfile(ExportProfile p) {
exportProfile = p;
}
}

View File

@@ -8,17 +8,21 @@ import java.awt.GridBagConstraints;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPanel;
import javax.swing.JComboBox;
public class BookInfoPanel extends JPanel {
JTextField title;
JTextField shortTitle;
JTextField author;
JTextField shortAuthor;
JTextField genre;
JTextField comment;
JTextField acx;
JTextField isbn;
JComboBox<ExportProfile> exportProfile;
public BookInfoPanel(String t, String a, String g, String c, String x, String i) {
public BookInfoPanel(String t, String st, String a, String sa, String g, String c, String x, String i, String epc) {
super();
Debug.trace();
setLayout(new GridBagLayout());
@@ -36,6 +40,15 @@ public class BookInfoPanel extends JPanel {
con.gridx = 0;
con.gridy++;
add(new JLabel("Short Title:"), con);
con.gridx = 1;
shortTitle = new JTextField(st);
shortTitle.setPreferredSize(new Dimension(200, 20));
add(shortTitle, con);
con.gridx = 0;
con.gridy++;
add(new JLabel("Author:"), con);
con.gridx = 1;
author = new JTextField(a);
@@ -45,6 +58,15 @@ public class BookInfoPanel extends JPanel {
con.gridx = 0;
con.gridy++;
add(new JLabel("Short Author:"), con);
con.gridx = 1;
shortAuthor = new JTextField(sa);
shortAuthor.setPreferredSize(new Dimension(200, 20));
add(shortAuthor, con);
con.gridx = 0;
con.gridy++;
add(new JLabel("Genre:"), con);
con.gridx = 1;
genre = new JTextField(g);
@@ -81,6 +103,20 @@ public class BookInfoPanel extends JPanel {
con.gridx = 0;
con.gridy++;
add(new JLabel("Export Profile:"), con);
con.gridx = 1;
exportProfile = new JComboBox<ExportProfile>();
for (ExportProfile profile : AudiobookRecorder.exportProfiles.values()) {
exportProfile.addItem(profile);
if (profile.getCode() == epc) {
exportProfile.setSelectedItem(profile);
}
}
add(exportProfile, con);
con.gridx = 0;
con.gridy++;
}
public String getTitle() { Debug.trace(); return title.getText(); }
@@ -97,6 +133,9 @@ public class BookInfoPanel extends JPanel {
}
return acx.getText();
}
public String getShortTitle() { Debug.trace(); return shortTitle.getText(); }
public String getShortAuthor() { Debug.trace(); return shortAuthor.getText(); }
public ExportProfile getExportProfile() { Debug.trace(); return (ExportProfile)exportProfile.getSelectedItem(); }
public void setTitle(String t) { Debug.trace(); title.setText(t); }
public void setAuthor(String a) { Debug.trace(); author.setText(a); }
@@ -104,5 +143,7 @@ public class BookInfoPanel extends JPanel {
public void setComment(String c) { Debug.trace(); comment.setText(c); }
public void setACX(String a) { Debug.trace(); acx.setText(a); }
public void setISBN(String i) { Debug.trace(); isbn.setText(i); }
public void setShortTitle(String t) { Debug.trace(); shortTitle.setText(t); }
public void setShortAuthor(String a) { Debug.trace(); shortAuthor.setText(a); }
public void setExportProfile(ExportProfile p) { Debug.trace(); exportProfile.setSelectedItem(p); }
}

View File

@@ -51,9 +51,6 @@ public class Chapter extends BookTreeNode {
String name;
String id;
int preGap;
int postGap;
String notes;
Book parentBook = null;
@@ -62,16 +59,12 @@ public class Chapter extends BookTreeNode {
Debug.trace();
id = i;
name = chaptername;
preGap = Options.getInteger("catenation.pre-chapter");
postGap = Options.getInteger("catenation.post-chapter");
}
public Chapter(Element root, DefaultTreeModel model) {
Debug.trace();
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");
@@ -89,8 +82,6 @@ public class Chapter extends BookTreeNode {
Debug.trace();
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");
@@ -160,26 +151,6 @@ public class Chapter extends BookTreeNode {
name = n;
}
public void setPreGap(int g) {
Debug.trace();
preGap = g;
}
public int getPreGap() {
Debug.trace();
return preGap;
}
public void setPostGap(int g) {
Debug.trace();
postGap = g;
}
public int getPostGap() {
Debug.trace();
return postGap;
}
public String createFilename(String format) {
String out = "";
@@ -198,13 +169,15 @@ public class Chapter extends BookTreeNode {
tokens.put("chapter.number", Integer.toString(getSequenceNumber()));
tokens.put("chapter.id", getId());
tokens.put("book.title", book.getTitle());
tokens.put("book.title.short", book.getShortTitle());
tokens.put("book.author", book.getAuthor());
tokens.put("book.author.short", book.getShortAuthor());
tokens.put("book.isbn", book.getISBN());
tokens.put("book.acx", book.getACX());
tokens.put("narrator.name", Options.get("narrator.name"));
tokens.put("narrator.initials", Options.get("narrator.initials"));
tokens.put("file.bitrate", Integer.toString(Options.getInteger("audio.export.bitrate")));
tokens.put("file.bitrate.kb", Integer.toString(Options.getInteger("audio.export.bitrate") / 1000));
tokens.put("file.bitrate", Integer.toString(book.getExportProfile().getExportBitrate()));
tokens.put("file.bitrate.kb", Integer.toString(book.getExportProfile().getExportBitrate() / 1000));
for(Map.Entry<String, String> entry : tokens.entrySet()) {
format = format.replace("{" + entry.getKey() + ":lower}", entry.getValue().toLowerCase());
@@ -214,7 +187,7 @@ public class Chapter extends BookTreeNode {
}
@SuppressWarnings("unchecked")
public void exportChapter(ProgressDialog exportDialog, String fnformat) throws
public void exportChapter(ProgressDialog exportDialog) throws
FileNotFoundException, IOException, InputFormatException, NotSupportedException,
EncoderException, UnsupportedTagException, InvalidDataException {
Debug.trace();
@@ -223,6 +196,10 @@ public class Chapter extends BookTreeNode {
Book book = getBook();
ExportProfile profile = book.getExportProfile();
String fnformat = profile.getExportFormat();
File export = book.getLocation("export");
if (!export.exists()) {
export.mkdirs();
@@ -243,9 +220,9 @@ public class Chapter extends BookTreeNode {
AudioAttributes audioAttributes = new AudioAttributes();
audioAttributes.setCodec("libmp3lame");
audioAttributes.setBitRate(Options.getInteger("audio.export.bitrate"));
audioAttributes.setSamplingRate(Options.getInteger("audio.export.samplerate"));
audioAttributes.setChannels(Options.getInteger("audio.export.channels")); //new Integer(2));
audioAttributes.setBitRate(profile.getExportBitrate());
audioAttributes.setSamplingRate(profile.getExportSamples());
audioAttributes.setChannels(profile.getExportChannels());
attributes.setFormat("mp3");
attributes.setAudioAttributes(audioAttributes);
@@ -270,7 +247,7 @@ public class Chapter extends BookTreeNode {
File taggedFile = new File(export, createFilename(fnformat) + ".mp3");
FileOutputStream fos = new FileOutputStream(exportFile);
data = getBook().getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter")));
data = getBook().getRoomNoise(profile.getGapPreChapter());
fullLength += data.length;
fos.write(data);
@@ -289,7 +266,7 @@ public class Chapter extends BookTreeNode {
if (s.hasMoreElements()) {
data = getBook().getRoomNoise(snt.getPostGap());
} else {
data = getBook().getRoomNoise(Utils.s2i(Options.get("catenation.post-chapter")));
data = getBook().getRoomNoise(profile.getGapPostChapter());
}
fullLength += data.length;
fos.write(data);
@@ -334,14 +311,16 @@ public class Chapter extends BookTreeNode {
public double getChapterLength() {
Debug.trace();
double totalTime = Options.getInteger("audio.recording.pre-chapter") / 1000d;
Book book = getBook();
ExportProfile exportProfile = book.getExportProfile();
double totalTime = exportProfile.getGapPreChapter() / 1000d;
for (Enumeration s = children(); s.hasMoreElements();) {
Sentence sentence = (Sentence)s.nextElement();
totalTime += sentence.getLength();
if (s.hasMoreElements()) {
totalTime += (sentence.getPostGap() / 1000d);
} else {
totalTime += Options.getInteger("audio.recording.post-chapter") / 1000d;
totalTime += exportProfile.getGapPostChapter() / 1000d;
}
}
return totalTime;
@@ -389,8 +368,6 @@ public class Chapter extends BookTreeNode {
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");
@@ -433,6 +410,9 @@ public class Chapter extends BookTreeNode {
@Override
public double getLength() {
Book book = getBook();
ExportProfile exportProfile = book.getExportProfile();
Debug.trace();
double len = 0;
for (Enumeration o = children(); o.hasMoreElements();) {
@@ -445,8 +425,8 @@ public class Chapter extends BookTreeNode {
}
if (len > 0) {
len += (getPreGap() / 1000d);
len += (getPostGap() / 1000d);
len += (exportProfile.getGapPreChapter() / 1000d);
len += (exportProfile.getGapPostChapter() / 1000d);
}
return len;
}

View File

@@ -0,0 +1,139 @@
package uk.co.majenko.audiobookrecorder;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.OutputKeys;
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;
import org.xml.sax.SAXException;
public class ExportProfile {
String name;
String code;
int export_bitrate;
int export_channels;
int export_samples;
String export_format;
int gap_pre_chapter;
int gap_post_chapter;
int gap_post_sentence;
int gap_followon;
int gap_post_paragraph;
int gap_post_section;
int audio_rms;
public ExportProfile() {
name = "Default";
code = "default";
export_bitrate = 128000;
export_channels = 1;
export_samples = 44100;
export_format = "{book.title} - {chapter.number} - {chapter.title}";
gap_pre_chapter = 1000;
gap_post_chapter = 1000;
gap_post_sentence = 500;
gap_followon = 300;
gap_post_paragraph = 800;
gap_post_section = 1200;
audio_rms = -18;
}
public ExportProfile(String filename) {
loadProfileFromFile(new File(filename));
}
public ExportProfile(File f) {
loadProfileFromFile(f);
}
public void loadProfileFromFile(File inputFile) {
if (inputFile.exists()) {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
Element root = doc.getDocumentElement();
Element export = getNode(root, "export");
Element gaps = getNode(root, "gaps");
Element audio = getNode(root, "audio");
name = getTextNode(root, "name");
code = getTextNode(root, "code");
export_bitrate = Utils.s2i(getTextNode(export, "bitrate"));
export_channels = Utils.s2i(getTextNode(export, "channels"));
export_samples = Utils.s2i(getTextNode(export, "samples"));
export_format = getTextNode(export, "format");
gap_pre_chapter = Utils.s2i(getTextNode(gaps, "pre-chapter"));
gap_post_chapter = Utils.s2i(getTextNode(gaps, "post-chapter"));
gap_post_sentence = Utils.s2i(getTextNode(gaps, "post-sentence"));
gap_followon = Utils.s2i(getTextNode(gaps, "followon"));
gap_post_paragraph = Utils.s2i(getTextNode(gaps, "post-paragraph"));
gap_post_section = Utils.s2i(getTextNode(gaps, "post-section"));
audio_rms = Utils.s2i(getTextNode(audio, "rms"));
} catch (ParserConfigurationException ex) {
System.err.println("Badly formatted XML file: " + inputFile.getPath());
} catch (SAXException ex) {
System.err.println("Badly formatted XML file: " + inputFile.getPath());
} catch (IOException ex) {
System.err.println("Error reading file: " + inputFile.getPath());
}
}
}
public Element getNode(Element r, String n) {
Debug.trace();
NodeList nl = r.getElementsByTagName(n);
if (nl == null) return null;
if (nl.getLength() == 0) return null;
return (Element)nl.item(0);
}
public String getTextNode(Element r, String n) {
Debug.trace();
return getTextNode(r, n, "");
}
public String getTextNode(Element r, String n, String d) {
Debug.trace();
Element node = getNode(r, n);
if (node == null) return d;
return node.getTextContent();
}
public String getName() { return name; }
public String getCode() { return code; }
public int getExportBitrate() { return export_bitrate; }
public int getExportChannels() { return export_channels; }
public int getExportSamples() { return export_samples; }
public String getExportFormat() { return export_format; }
public int getGapPreChapter() { return gap_pre_chapter; }
public int getGapPostChapter() { return gap_post_chapter; }
public int getGapFollowon() { return gap_followon; }
public int getGapPostSentence() { return gap_post_sentence; }
public int getGapPostParagraph() { return gap_post_paragraph; }
public int getGapPostSection() { return gap_post_section; }
public int getAudioRMS() { return audio_rms; }
public String toString() {
return getName();
}
}

View File

@@ -377,19 +377,7 @@ public class Options extends JDialog {
addSeparator(optionsPanel);
preChapterGap = addSpinner(optionsPanel, "Default pre-chapter gap:", 0, 5000, 100, getInteger("catenation.pre-chapter"), "ms", "How much room noise to add at the beginning of a chapter.");
postChapterGap = addSpinner(optionsPanel, "Default post-chapter gap:", 0, 5000, 100, getInteger("catenation.post-chapter"), "ms", "How much room noise to add to the end of a chapter.");
postSentenceGap = addSpinner(optionsPanel, "Default post-sentence gap:", 0, 5000, 100, getInteger("catenation.post-sentence"), "ms", "How much room noise to add between normal sentences.");
shortSentenceGap = addSpinner(optionsPanel, "Short post-sentence gap:", 0, 5000, 100, getInteger("catenation.short-sentence"), "ms", "How much room noise to add between 'continuations'.");
postParagraphGap = addSpinner(optionsPanel, "Default post-paragraph gap:", 0, 5000, 100, getInteger("catenation.post-paragraph"), "ms", "How much room noise to add between paragraphs.");
postSectionGap = addSpinner(optionsPanel, "Default post-section gap:", 0, 5000, 100, getInteger("catenation.post-section"), "ms", "How much room noise to add between sections.");
addSeparator(optionsPanel);
ffmpegLocation = addFilePath(optionsPanel, "FFMPEG location:", get("path.ffmpeg"), false, "Path to your ffmpeg executable.");
bitRate = addDropdown(optionsPanel, "Export bitrate:", getBitrates(), get("audio.export.bitrate"), "The MP3 bitrate to produce");
channels = addDropdown(optionsPanel, "Export channels:", getChannelCountList(), get("audio.export.channels"), "Mono or stereo MP3 production");
exportRate = addDropdown(optionsPanel, "Export sample rate:", getSampleRateList(), get("audio.export.samplerate"), "Sample frequency of the produced MP3");
addSeparator(optionsPanel);

View File

@@ -198,7 +198,6 @@ public class Sentence extends BookTreeNode implements Cacheable {
id = UUID.randomUUID().toString();
text = id;
setUserObject(text);
postGap = Options.getInteger("catenation.post-sentence");
}
public Sentence(String i, String t) {
@@ -207,7 +206,6 @@ public class Sentence extends BookTreeNode implements Cacheable {
id = i;
text = t;
setUserObject(text);
postGap = Options.getInteger("catenation.post-sentence");
}
public Sentence(Element root) {
@@ -990,8 +988,8 @@ public class Sentence extends BookTreeNode implements Cacheable {
Debug.trace();
if (locked) return gain;
int targetLow = Options.getInteger("audio.recording.rms.low");
int targetHigh = Options.getInteger("audio.recording.rms.high");
int targetLow = getBook().getExportProfile().getAudioRMS();
int targetHigh = getBook().getExportProfile().getAudioRMS();
long ts = System.currentTimeMillis();
while ((int)getRMS() < targetLow) {
@@ -1639,13 +1637,13 @@ public class Sentence extends BookTreeNode implements Cacheable {
public void setPostGapType(String t) {
Debug.trace();
if (t == null || t.equals("none")) {
if (getPostGap() == Options.getInteger("catenation.short-sentence")) {
if (getPostGap() == getBook().getExportProfile().getGapFollowon()) {
t = "continuation";
} else if (getPostGap() == Options.getInteger("catenation.post-paragraph")) {
} else if (getPostGap() == getBook().getExportProfile().getGapPostParagraph()) {
t = "paragraph";
} else if (getPostGap() == Options.getInteger("catenation.post-section")) {
} else if (getPostGap() == getBook().getExportProfile().getGapPostSection()) {
t = "section";
} else if (getPostGap() == Options.getInteger("catenation.post-sentence")) {
} else if (getPostGap() == getBook().getExportProfile().getGapPostSentence()) {
t = "sentence";
} else {
t = "sentence";
@@ -1661,13 +1659,13 @@ public class Sentence extends BookTreeNode implements Cacheable {
postGapType = "sentence";
}
if (postGapType.equals("continuation")) {
setPostGap(Options.getInteger("catenation.short-sentence"));
setPostGap(getBook().getExportProfile().getGapFollowon());
} else if (postGapType.equals("paragraph")) {
setPostGap(Options.getInteger("catenation.post-paragraph"));
setPostGap(getBook().getExportProfile().getGapPostParagraph());
} else if (postGapType.equals("section")) {
setPostGap(Options.getInteger("catenation.post-section"));
setPostGap(getBook().getExportProfile().getGapPostSection());
} else {
setPostGap(Options.getInteger("catenation.post-sentence"));
setPostGap(getBook().getExportProfile().getGapPostSentence());
}
}