Finally fixed pesky memory leak

This commit is contained in:
2019-08-13 14:02:14 +01:00
parent 04fea4acb2
commit 289834021f
4 changed files with 103 additions and 43 deletions

View File

@@ -598,56 +598,76 @@ public class AudiobookRecorder extends JFrame {
centralPanel.getActionMap().put("startRecord", new AbstractAction() { centralPanel.getActionMap().put("startRecord", new AbstractAction() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return; if (!getLock()) return;
if (bookTree.isEditing()) {
freeLock();
return;
}
if (getNoiseFloor() == 0) { if (getNoiseFloor() == 0) {
freeLock();
alertNoRoomNoise(); alertNoRoomNoise();
return; return;
} }
if (!getLock()) return;
startRecording(); startRecording();
} }
}); });
centralPanel.getActionMap().put("startRecordShort", new AbstractAction() { centralPanel.getActionMap().put("startRecordShort", new AbstractAction() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return; if (!getLock()) return;
if (bookTree.isEditing()) {
freeLock();
return;
}
if (getNoiseFloor() == 0) { if (getNoiseFloor() == 0) {
freeLock();
alertNoRoomNoise(); alertNoRoomNoise();
return; return;
} }
if (!getLock()) return;
startRecordingShort(); startRecordingShort();
} }
}); });
centralPanel.getActionMap().put("startRecordNewPara", new AbstractAction() { centralPanel.getActionMap().put("startRecordNewPara", new AbstractAction() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return; if (!getLock()) return;
if (getNoiseFloor() == 0) { if (bookTree.isEditing()) {
alertNoRoomNoise(); freeLock();
return;
}
if (getNoiseFloor() == 0) {
alertNoRoomNoise();
freeLock();
return; return;
} }
if (!getLock()) return;
startRecordingNewParagraph(); startRecordingNewParagraph();
} }
}); });
centralPanel.getActionMap().put("startRecordNewSection", new AbstractAction() { centralPanel.getActionMap().put("startRecordNewSection", new AbstractAction() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return; if (!getLock()) return;
if (bookTree.isEditing()) {
freeLock();
return;
}
if (getNoiseFloor() == 0) { if (getNoiseFloor() == 0) {
freeLock();
alertNoRoomNoise(); alertNoRoomNoise();
return; return;
} }
if (!getLock()) return;
startRecordingNewSection(); startRecordingNewSection();
} }
}); });
centralPanel.getActionMap().put("startRerecord", new AbstractAction() { centralPanel.getActionMap().put("startRerecord", new AbstractAction() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return; if (!getLock()) return;
if (bookTree.isEditing()) {
freeLock();
return;
}
if (getNoiseFloor() == 0) { if (getNoiseFloor() == 0) {
freeLock();
alertNoRoomNoise(); alertNoRoomNoise();
return; return;
} }
if (!getLock()) return;
startReRecording(); startReRecording();
} }
}); });
@@ -1365,7 +1385,6 @@ public class AudiobookRecorder extends JFrame {
if (s.startRecording()) { if (s.startRecording()) {
recording = (Sentence)selectedNode; recording = (Sentence)selectedNode;
System.err.println("Starting flash");
centralPanel.setFlash(true); centralPanel.setFlash(true);
} }
} }
@@ -1415,7 +1434,6 @@ public class AudiobookRecorder extends JFrame {
if (s.startRecording()) { if (s.startRecording()) {
recording = s; recording = s;
System.err.println("Starting flash");
centralPanel.setFlash(true); centralPanel.setFlash(true);
} }
} }
@@ -1466,7 +1484,6 @@ public class AudiobookRecorder extends JFrame {
if (s.startRecording()) { if (s.startRecording()) {
recording = s; recording = s;
System.err.println("Starting flash");
centralPanel.setFlash(true); centralPanel.setFlash(true);
} }
} }
@@ -1516,7 +1533,6 @@ public class AudiobookRecorder extends JFrame {
if (s.startRecording()) { if (s.startRecording()) {
recording = s; recording = s;
System.err.println("Starting flash");
centralPanel.setFlash(true); centralPanel.setFlash(true);
} }
} }
@@ -1566,29 +1582,23 @@ public class AudiobookRecorder extends JFrame {
if (s.startRecording()) { if (s.startRecording()) {
recording = s; recording = s;
System.err.println("Starting flash");
centralPanel.setFlash(true); centralPanel.setFlash(true);
} }
} }
public void stopRecording() { public void stopRecording() {
System.err.println("Record stop requested");
if (recording == null) return; if (recording == null) return;
recording.stopRecording(); recording.stopRecording();
System.err.println("Reloading model");
bookTreeModel.reload(book); bookTreeModel.reload(book);
bookTree.expandPath(new TreePath(((DefaultMutableTreeNode)recording.getParent()).getPath())); bookTree.expandPath(new TreePath(((DefaultMutableTreeNode)recording.getParent()).getPath()));
bookTree.setSelectionPath(new TreePath(recording.getPath())); bookTree.setSelectionPath(new TreePath(recording.getPath()));
bookTree.scrollPathToVisible(new TreePath(recording.getPath())); bookTree.scrollPathToVisible(new TreePath(recording.getPath()));
System.err.println("Stopping flash");
centralPanel.setFlash(false); centralPanel.setFlash(false);
recording = null; recording = null;
System.err.println("Saving book");
saveBookStructure(); saveBookStructure();
System.err.println("Stop request complete");
} }
public void deleteLastRecording() { public void deleteLastRecording() {
@@ -3001,4 +3011,5 @@ public class AudiobookRecorder extends JFrame {
public void stopLock() { public void stopLock() {
state = STOPPING; state = STOPPING;
} }
} }

View File

@@ -28,5 +28,6 @@ public class CacheManager {
public static void removeFromCache(Cacheable c) { public static void removeFromCache(Cacheable c) {
cache.remove(c); cache.remove(c);
c.clearCache();
} }
} }

View File

@@ -155,31 +155,24 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
} }
public boolean startRecording() { public boolean startRecording() {
System.err.println("Starting record");
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);
return false; return false;
} }
System.err.println("Removing object from cache");
CacheManager.removeFromCache(this); CacheManager.removeFromCache(this);
System.err.println("Creating record thread");
recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat()); recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat());
System.err.println("Starting record thread");
Thread rc = new Thread(recordingThread); Thread rc = new Thread(recordingThread);
rc.setDaemon(true); rc.setDaemon(true);
rc.start(); rc.start();
System.err.println("Recording started");
return true; return true;
} }
public void stopRecording() { public void stopRecording() {
System.err.println("Stopping recording...");
recordingThread.stopRecording(); recordingThread.stopRecording();
System.err.println("Waiting for stop to complete...");
while (recordingThread.isRunning()) { while (recordingThread.isRunning()) {
try { try {
Thread.sleep(10); Thread.sleep(10);
@@ -188,14 +181,11 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
} }
} }
System.err.println("Removing object from cache...");
CacheManager.removeFromCache(this); CacheManager.removeFromCache(this);
audioData = null; audioData = null;
processedAudio = null; processedAudio = null;
System.err.println("Running trim and recognition...");
if (!id.equals("room-noise")) { if (!id.equals("room-noise")) {
String tm = Options.get("audio.recording.trim"); String tm = Options.get("audio.recording.trim");
if (tm.equals("peak")) { if (tm.equals("peak")) {
@@ -207,7 +197,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
recognise(); recognise();
} }
} }
System.err.println("Recording stop complete");
} }
public static final int FFTBuckets = 1024; public static final int FFTBuckets = 1024;
@@ -225,7 +215,11 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
} else { } else {
samples = getProcessedAudioData(); samples = getProcessedAudioData();
} }
if (samples == null) return; if (samples == null) {
System.err.println("Error: loading data failed!");
return;
}
int blocks = samples.length / 4096 + 1; int blocks = samples.length / 4096 + 1;
@@ -264,6 +258,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
block++; block++;
} }
int limit = Options.getInteger("audio.recording.trim.fft"); int limit = Options.getInteger("audio.recording.trim.fft");
// Find first block with > 1 intensity and subtract one. // Find first block with > 1 intensity and subtract one.
@@ -300,7 +295,10 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
if (endOffset <= startOffset) endOffset = startOffset + 4096; if (endOffset <= startOffset) endOffset = startOffset + 4096;
if (endOffset < 0) endOffset = 0; if (endOffset < 0) endOffset = 0;
if (endOffset >= samples.length) endOffset = samples.length; if (endOffset >= samples.length) endOffset = samples.length;
updateCrossings(); updateCrossings(useRaw);
intens = null;
samples = null;
System.gc();
} }
@@ -355,7 +353,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
if (startOffset < 0) startOffset = 0; if (startOffset < 0) startOffset = 0;
if (endOffset >= samples.length) endOffset = samples.length-1; if (endOffset >= samples.length) endOffset = samples.length-1;
updateCrossings(); updateCrossings(useRaw);
} }
public String getId() { public String getId() {
@@ -439,19 +437,31 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
} }
public void updateCrossings() { public void updateCrossings() {
updateStartCrossing(); updateCrossings(false);
updateEndCrossing(); }
public void updateCrossings(boolean useRaw) {
updateStartCrossing(useRaw);
updateEndCrossing(useRaw);
} }
public void updateStartCrossing() { public void updateStartCrossing() {
updateStartCrossing(false);
}
public void updateStartCrossing(boolean useRaw) {
if (crossStartOffset == -1) { if (crossStartOffset == -1) {
crossStartOffset = findNearestZeroCrossing(startOffset, 4096); crossStartOffset = findNearestZeroCrossing(useRaw, startOffset, 4096);
} }
} }
public void updateEndCrossing() { public void updateEndCrossing() {
updateEndCrossing(false);
}
public void updateEndCrossing(boolean useRaw) {
if (crossEndOffset == -1) { if (crossEndOffset == -1) {
crossEndOffset = findNearestZeroCrossing(endOffset, 4096); crossEndOffset = findNearestZeroCrossing(useRaw, endOffset, 4096);
} }
} }
@@ -580,7 +590,16 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
} }
public int findNearestZeroCrossing(int pos, int range) { public int findNearestZeroCrossing(int pos, int range) {
double[][] data = getProcessedAudioData(); return findNearestZeroCrossing(false, pos, range);
}
public int findNearestZeroCrossing(boolean useRaw, int pos, int range) {
double[][] data = null;
if (useRaw) {
data = getRawAudioData();
} else {
data = getProcessedAudioData();
}
if (data == null) return 0; if (data == null) return 0;
if (data.length == 0) return 0; if (data.length == 0) return 0;
@@ -654,9 +673,18 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
} }
public double getPeakValue() { public double getPeakValue() {
return getPeakValue(false);
}
public double getPeakValue(boolean useRaw) {
double oldGain = gain; double oldGain = gain;
gain = 1.0d; gain = 1.0d;
double[][] samples = getProcessedAudioData(); double[][] samples = null;
if (useRaw) {
samples = getRawAudioData();
} else {
samples = getProcessedAudioData();
}
gain = oldGain; gain = oldGain;
if (samples == null) { if (samples == null) {
return 0; return 0;
@@ -944,10 +972,16 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
} }
public void loadFile() { public void loadFile() {
if (audioData != null) return; if (audioData != null) {
return;
}
File f = getFile(); File f = getFile();
try { try {
if (!f.exists()) {
System.err.println("TODO: Race condition: wav file doesn't exist yet");
return;
}
AudioInputStream s = AudioSystem.getAudioInputStream(f); AudioInputStream s = AudioSystem.getAudioInputStream(f);
AudioFormat format = getAudioFormat(); AudioFormat format = getAudioFormat();
@@ -967,6 +1001,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
audioData = samples; audioData = samples;
CacheManager.addToCache(this); CacheManager.addToCache(this);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
} }
} }

View File

@@ -63,4 +63,17 @@ public class Utils {
} }
} }
} }
static long millis = System.currentTimeMillis();
public static void report(String tag) {
long t = System.currentTimeMillis();
long d = t - millis;
millis = t;
System.err.println(String.format("%10d - %10s : %8d | %8d | %8d", d, tag,
Runtime.getRuntime().totalMemory(),
Runtime.getRuntime().maxMemory(),
Runtime.getRuntime().freeMemory()
));
}
} }