From 289834021fb825fdfc94561d6d8624c8c03c8499 Mon Sep 17 00:00:00 2001 From: Matt Jenkins Date: Tue, 13 Aug 2019 14:02:14 +0100 Subject: [PATCH] Finally fixed pesky memory leak --- .../audiobookrecorder/AudiobookRecorder.java | 55 +++++++------ .../audiobookrecorder/CacheManager.java | 1 + .../majenko/audiobookrecorder/Sentence.java | 77 ++++++++++++++----- .../co/majenko/audiobookrecorder/Utils.java | 13 ++++ 4 files changed, 103 insertions(+), 43 deletions(-) diff --git a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java index 520dcbc..2533fd7 100644 --- a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java +++ b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java @@ -598,56 +598,76 @@ public class AudiobookRecorder extends JFrame { centralPanel.getActionMap().put("startRecord", new AbstractAction() { public void actionPerformed(ActionEvent e) { - if (bookTree.isEditing()) return; + if (!getLock()) return; + if (bookTree.isEditing()) { + freeLock(); + return; + } if (getNoiseFloor() == 0) { + freeLock(); alertNoRoomNoise(); return; } - if (!getLock()) return; startRecording(); } }); centralPanel.getActionMap().put("startRecordShort", new AbstractAction() { public void actionPerformed(ActionEvent e) { - if (bookTree.isEditing()) return; + if (!getLock()) return; + if (bookTree.isEditing()) { + freeLock(); + return; + } if (getNoiseFloor() == 0) { + freeLock(); alertNoRoomNoise(); return; } - if (!getLock()) return; startRecordingShort(); } }); centralPanel.getActionMap().put("startRecordNewPara", new AbstractAction() { public void actionPerformed(ActionEvent e) { - if (bookTree.isEditing()) return; - if (getNoiseFloor() == 0) { - alertNoRoomNoise(); + if (!getLock()) return; + if (bookTree.isEditing()) { + freeLock(); + return; + } + if (getNoiseFloor() == 0) { + alertNoRoomNoise(); + freeLock(); return; } - if (!getLock()) return; startRecordingNewParagraph(); } }); centralPanel.getActionMap().put("startRecordNewSection", new AbstractAction() { public void actionPerformed(ActionEvent e) { - if (bookTree.isEditing()) return; + if (!getLock()) return; + if (bookTree.isEditing()) { + freeLock(); + return; + } if (getNoiseFloor() == 0) { + freeLock(); alertNoRoomNoise(); return; } - if (!getLock()) return; startRecordingNewSection(); } }); centralPanel.getActionMap().put("startRerecord", new AbstractAction() { public void actionPerformed(ActionEvent e) { - if (bookTree.isEditing()) return; + if (!getLock()) return; + if (bookTree.isEditing()) { + freeLock(); + return; + } if (getNoiseFloor() == 0) { + freeLock(); alertNoRoomNoise(); return; } - if (!getLock()) return; startReRecording(); } }); @@ -1365,7 +1385,6 @@ public class AudiobookRecorder extends JFrame { if (s.startRecording()) { recording = (Sentence)selectedNode; - System.err.println("Starting flash"); centralPanel.setFlash(true); } } @@ -1415,7 +1434,6 @@ public class AudiobookRecorder extends JFrame { if (s.startRecording()) { recording = s; - System.err.println("Starting flash"); centralPanel.setFlash(true); } } @@ -1466,7 +1484,6 @@ public class AudiobookRecorder extends JFrame { if (s.startRecording()) { recording = s; - System.err.println("Starting flash"); centralPanel.setFlash(true); } } @@ -1516,7 +1533,6 @@ public class AudiobookRecorder extends JFrame { if (s.startRecording()) { recording = s; - System.err.println("Starting flash"); centralPanel.setFlash(true); } } @@ -1566,29 +1582,23 @@ public class AudiobookRecorder extends JFrame { if (s.startRecording()) { recording = s; - System.err.println("Starting flash"); centralPanel.setFlash(true); } } public void stopRecording() { - System.err.println("Record stop requested"); if (recording == null) return; recording.stopRecording(); - System.err.println("Reloading model"); bookTreeModel.reload(book); bookTree.expandPath(new TreePath(((DefaultMutableTreeNode)recording.getParent()).getPath())); bookTree.setSelectionPath(new TreePath(recording.getPath())); bookTree.scrollPathToVisible(new TreePath(recording.getPath())); - System.err.println("Stopping flash"); centralPanel.setFlash(false); recording = null; - System.err.println("Saving book"); saveBookStructure(); - System.err.println("Stop request complete"); } public void deleteLastRecording() { @@ -3001,4 +3011,5 @@ public class AudiobookRecorder extends JFrame { public void stopLock() { state = STOPPING; } + } diff --git a/src/uk/co/majenko/audiobookrecorder/CacheManager.java b/src/uk/co/majenko/audiobookrecorder/CacheManager.java index 8afd908..5350d06 100644 --- a/src/uk/co/majenko/audiobookrecorder/CacheManager.java +++ b/src/uk/co/majenko/audiobookrecorder/CacheManager.java @@ -28,5 +28,6 @@ public class CacheManager { public static void removeFromCache(Cacheable c) { cache.remove(c); + c.clearCache(); } } diff --git a/src/uk/co/majenko/audiobookrecorder/Sentence.java b/src/uk/co/majenko/audiobookrecorder/Sentence.java index 7b940cb..5432808 100644 --- a/src/uk/co/majenko/audiobookrecorder/Sentence.java +++ b/src/uk/co/majenko/audiobookrecorder/Sentence.java @@ -155,31 +155,24 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } public boolean startRecording() { - System.err.println("Starting record"); if (AudiobookRecorder.window.microphone == null) { JOptionPane.showMessageDialog(AudiobookRecorder.window, "Microphone not started. Start the microphone first.", "Error", JOptionPane.ERROR_MESSAGE); return false; } - System.err.println("Removing object from cache"); CacheManager.removeFromCache(this); - System.err.println("Creating record thread"); recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat()); - System.err.println("Starting record thread"); Thread rc = new Thread(recordingThread); rc.setDaemon(true); rc.start(); - System.err.println("Recording started"); return true; } public void stopRecording() { - System.err.println("Stopping recording..."); recordingThread.stopRecording(); - System.err.println("Waiting for stop to complete..."); while (recordingThread.isRunning()) { try { Thread.sleep(10); @@ -188,14 +181,11 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } } - System.err.println("Removing object from cache..."); - CacheManager.removeFromCache(this); audioData = null; processedAudio = null; - System.err.println("Running trim and recognition..."); if (!id.equals("room-noise")) { String tm = Options.get("audio.recording.trim"); if (tm.equals("peak")) { @@ -207,7 +197,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { recognise(); } } - System.err.println("Recording stop complete"); + } public static final int FFTBuckets = 1024; @@ -225,7 +215,11 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } else { samples = getProcessedAudioData(); } - if (samples == null) return; + if (samples == null) { + System.err.println("Error: loading data failed!"); + return; + } + int blocks = samples.length / 4096 + 1; @@ -264,6 +258,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { block++; } + int limit = Options.getInteger("audio.recording.trim.fft"); // 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 < 0) endOffset = 0; 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 (endOffset >= samples.length) endOffset = samples.length-1; - updateCrossings(); + updateCrossings(useRaw); } public String getId() { @@ -439,19 +437,31 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } public void updateCrossings() { - updateStartCrossing(); - updateEndCrossing(); + updateCrossings(false); + } + + public void updateCrossings(boolean useRaw) { + updateStartCrossing(useRaw); + updateEndCrossing(useRaw); } public void updateStartCrossing() { + updateStartCrossing(false); + } + + public void updateStartCrossing(boolean useRaw) { if (crossStartOffset == -1) { - crossStartOffset = findNearestZeroCrossing(startOffset, 4096); + crossStartOffset = findNearestZeroCrossing(useRaw, startOffset, 4096); } } public void updateEndCrossing() { + updateEndCrossing(false); + } + + public void updateEndCrossing(boolean useRaw) { 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) { - 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.length == 0) return 0; @@ -654,9 +673,18 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } public double getPeakValue() { + return getPeakValue(false); + } + + public double getPeakValue(boolean useRaw) { double oldGain = gain; gain = 1.0d; - double[][] samples = getProcessedAudioData(); + double[][] samples = null; + if (useRaw) { + samples = getRawAudioData(); + } else { + samples = getProcessedAudioData(); + } gain = oldGain; if (samples == null) { return 0; @@ -944,10 +972,16 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } public void loadFile() { - if (audioData != null) return; + if (audioData != null) { + return; + } File f = getFile(); try { + if (!f.exists()) { + System.err.println("TODO: Race condition: wav file doesn't exist yet"); + return; + } AudioInputStream s = AudioSystem.getAudioInputStream(f); AudioFormat format = getAudioFormat(); @@ -967,6 +1001,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { audioData = samples; CacheManager.addToCache(this); } catch (Exception e) { + e.printStackTrace(); } } diff --git a/src/uk/co/majenko/audiobookrecorder/Utils.java b/src/uk/co/majenko/audiobookrecorder/Utils.java index 825e004..8bf2edc 100644 --- a/src/uk/co/majenko/audiobookrecorder/Utils.java +++ b/src/uk/co/majenko/audiobookrecorder/Utils.java @@ -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() + )); + } }