Added zero crossing detection #7
This commit is contained in:
@@ -257,6 +257,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
selectedSentence.autoTrimSampleFFT();
|
selectedSentence.autoTrimSampleFFT();
|
||||||
sampleWaveform.setData(selectedSentence.getAudioData());
|
sampleWaveform.setData(selectedSentence.getAudioData());
|
||||||
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
||||||
|
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
||||||
startOffset.setValue(selectedSentence.getStartOffset());
|
startOffset.setValue(selectedSentence.getStartOffset());
|
||||||
endOffset.setValue(selectedSentence.getEndOffset());
|
endOffset.setValue(selectedSentence.getEndOffset());
|
||||||
postSentenceGap.setValue(selectedSentence.getPostGap());
|
postSentenceGap.setValue(selectedSentence.getPostGap());
|
||||||
@@ -272,6 +273,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
selectedSentence.autoTrimSamplePeak();
|
selectedSentence.autoTrimSamplePeak();
|
||||||
sampleWaveform.setData(selectedSentence.getAudioData());
|
sampleWaveform.setData(selectedSentence.getAudioData());
|
||||||
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
|
||||||
|
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
|
||||||
startOffset.setValue(selectedSentence.getStartOffset());
|
startOffset.setValue(selectedSentence.getStartOffset());
|
||||||
endOffset.setValue(selectedSentence.getEndOffset());
|
endOffset.setValue(selectedSentence.getEndOffset());
|
||||||
postSentenceGap.setValue(selectedSentence.getPostGap());
|
postSentenceGap.setValue(selectedSentence.getPostGap());
|
||||||
@@ -292,6 +294,8 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (selectedSentence != null) {
|
if (selectedSentence != null) {
|
||||||
selectedSentence.setStartOffset((Integer)ob.getValue());
|
selectedSentence.setStartOffset((Integer)ob.getValue());
|
||||||
sampleWaveform.setLeftMarker((Integer)ob.getValue());
|
sampleWaveform.setLeftMarker((Integer)ob.getValue());
|
||||||
|
selectedSentence.updateStartCrossing();
|
||||||
|
sampleWaveform.setLeftAltMarker(selectedSentence.getStartCrossing());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -302,6 +306,8 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (selectedSentence != null) {
|
if (selectedSentence != null) {
|
||||||
selectedSentence.setEndOffset((Integer)ob.getValue());
|
selectedSentence.setEndOffset((Integer)ob.getValue());
|
||||||
sampleWaveform.setRightMarker((Integer)ob.getValue());
|
sampleWaveform.setRightMarker((Integer)ob.getValue());
|
||||||
|
selectedSentence.updateEndCrossing();
|
||||||
|
sampleWaveform.setRightAltMarker(selectedSentence.getEndCrossing());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1170,6 +1176,8 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
selectedSentence = s;
|
selectedSentence = s;
|
||||||
sampleWaveform.setData(s.getAudioData());
|
sampleWaveform.setData(s.getAudioData());
|
||||||
sampleWaveform.setMarkers(s.getStartOffset(), s.getEndOffset());
|
sampleWaveform.setMarkers(s.getStartOffset(), s.getEndOffset());
|
||||||
|
s.updateCrossings();
|
||||||
|
sampleWaveform.setAltMarkers(s.getStartCrossing(), s.getEndCrossing());
|
||||||
startOffset.setValue(s.getStartOffset());
|
startOffset.setValue(s.getStartOffset());
|
||||||
endOffset.setValue(s.getEndOffset());
|
endOffset.setValue(s.getEndOffset());
|
||||||
postSentenceGap.setValue(s.getPostGap());
|
postSentenceGap.setValue(s.getPostGap());
|
||||||
@@ -1532,7 +1540,6 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
File mp3File = new File(export, name + "-untagged.mp3");
|
File mp3File = new File(export, name + "-untagged.mp3");
|
||||||
File taggedFile = new File(export, name + ".mp3");
|
File taggedFile = new File(export, name + ".mp3");
|
||||||
|
|
||||||
System.err.println(attributes);
|
|
||||||
encoder.encode(wavFile, mp3File, attributes);
|
encoder.encode(wavFile, mp3File, attributes);
|
||||||
|
|
||||||
Mp3File id3 = new Mp3File(mp3File);
|
Mp3File id3 = new Mp3File(mp3File);
|
||||||
|
|||||||
@@ -14,12 +14,10 @@ public class CacheManager {
|
|||||||
cache.add(ob);
|
cache.add(ob);
|
||||||
} else {
|
} else {
|
||||||
ob.clearCache();
|
ob.clearCache();
|
||||||
System.err.println("Purged " + ob);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.add(c);
|
cache.add(c);
|
||||||
System.err.println("Cached " + c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setCacheSize(int c) {
|
public static void setCacheSize(int c) {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
int postGap;
|
int postGap;
|
||||||
int startOffset = 0;
|
int startOffset = 0;
|
||||||
int endOffset = 0;
|
int endOffset = 0;
|
||||||
|
int crossStartOffset = -1;
|
||||||
|
int crossEndOffset = -1;
|
||||||
|
|
||||||
int sampleSize = -1;
|
int sampleSize = -1;
|
||||||
|
|
||||||
@@ -132,6 +134,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void autoTrimSampleFFT() {
|
public void autoTrimSampleFFT() {
|
||||||
|
crossStartOffset = -1;
|
||||||
|
crossEndOffset = -1;
|
||||||
int[] samples = getAudioData();
|
int[] samples = getAudioData();
|
||||||
if (samples == null) return;
|
if (samples == null) return;
|
||||||
|
|
||||||
@@ -205,10 +209,13 @@ 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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void autoTrimSamplePeak() {
|
public void autoTrimSamplePeak() {
|
||||||
|
crossStartOffset = -1;
|
||||||
|
crossEndOffset = -1;
|
||||||
int[] samples = getAudioData();
|
int[] samples = getAudioData();
|
||||||
if (samples == null) return;
|
if (samples == null) return;
|
||||||
int noiseFloor = AudiobookRecorder.window.getNoiseFloor();
|
int noiseFloor = AudiobookRecorder.window.getNoiseFloor();
|
||||||
@@ -247,6 +254,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@@ -349,12 +357,40 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getStartCrossing() {
|
||||||
|
return crossStartOffset;
|
||||||
|
}
|
||||||
|
|
||||||
public int getStartOffset() {
|
public int getStartOffset() {
|
||||||
return startOffset;
|
return startOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateCrossings() {
|
||||||
|
updateStartCrossing();
|
||||||
|
updateEndCrossing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateStartCrossing() {
|
||||||
|
if (crossStartOffset == -1) {
|
||||||
|
crossStartOffset = findNearestZeroCrossing(startOffset, 4096);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateEndCrossing() {
|
||||||
|
if (crossEndOffset == -1) {
|
||||||
|
crossEndOffset = findNearestZeroCrossing(endOffset, 4096);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setStartOffset(int o) {
|
public void setStartOffset(int o) {
|
||||||
startOffset = o;
|
if (startOffset != o) {
|
||||||
|
startOffset = o;
|
||||||
|
crossStartOffset = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEndCrossing() {
|
||||||
|
return crossEndOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEndOffset() {
|
public int getEndOffset() {
|
||||||
@@ -362,7 +398,10 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setEndOffset(int o) {
|
public void setEndOffset(int o) {
|
||||||
endOffset = o;
|
if (endOffset != o) {
|
||||||
|
endOffset = o;
|
||||||
|
crossEndOffset = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSampleSize() {
|
public int getSampleSize() {
|
||||||
@@ -411,7 +450,9 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
long len = s.getFrameLength();
|
long len = s.getFrameLength();
|
||||||
int frameSize = format.getFrameSize();
|
int frameSize = format.getFrameSize();
|
||||||
|
|
||||||
int pos = startOffset * frameSize;
|
updateCrossings();
|
||||||
|
|
||||||
|
int pos = crossStartOffset * frameSize;
|
||||||
|
|
||||||
SourceDataLine play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
SourceDataLine play = AudioSystem.getSourceDataLine(format, Options.getPlaybackMixer());
|
||||||
play.open(format);
|
play.open(format);
|
||||||
@@ -422,7 +463,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
s.skip(pos);
|
s.skip(pos);
|
||||||
|
|
||||||
while (pos < endOffset * frameSize) {
|
while (pos < crossEndOffset * frameSize) {
|
||||||
int nr = s.read(buffer);
|
int nr = s.read(buffer);
|
||||||
pos += nr;
|
pos += nr;
|
||||||
|
|
||||||
@@ -438,13 +479,14 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public byte[] getRawAudioData() {
|
public byte[] getRawAudioData() {
|
||||||
File f = getFile();
|
File f = getFile();
|
||||||
try {
|
try {
|
||||||
|
updateCrossings();
|
||||||
AudioInputStream s = AudioSystem.getAudioInputStream(f);
|
AudioInputStream s = AudioSystem.getAudioInputStream(f);
|
||||||
AudioFormat format = s.getFormat();
|
AudioFormat format = s.getFormat();
|
||||||
int frameSize = format.getFrameSize();
|
int frameSize = format.getFrameSize();
|
||||||
int length = endOffset - startOffset;
|
int length = crossEndOffset - crossStartOffset;
|
||||||
byte[] data = new byte[length * frameSize];
|
byte[] data = new byte[length * frameSize];
|
||||||
|
|
||||||
s.skip(startOffset * frameSize);
|
s.skip(crossStartOffset * frameSize);
|
||||||
|
|
||||||
s.read(data);
|
s.read(data);
|
||||||
|
|
||||||
@@ -497,8 +539,6 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
System.err.println("Decimated from " + length + " to " + newLen);
|
|
||||||
|
|
||||||
ByteArrayInputStream bas = new ByteArrayInputStream(decimated);
|
ByteArrayInputStream bas = new ByteArrayInputStream(decimated);
|
||||||
recognizer.startRecognition(bas);
|
recognizer.startRecognition(bas);
|
||||||
SpeechResult result;
|
SpeechResult result;
|
||||||
@@ -546,4 +586,40 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public boolean lockedInCache() {
|
public boolean lockedInCache() {
|
||||||
return id.equals("room-noise");
|
return id.equals("room-noise");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int findNearestZeroCrossing(int pos, int range) {
|
||||||
|
int[] data = getAudioData();
|
||||||
|
|
||||||
|
if (pos < 0) pos = 0;
|
||||||
|
if (pos >= data.length) pos = data.length-1;
|
||||||
|
|
||||||
|
int backwards = pos;
|
||||||
|
int forwards = pos;
|
||||||
|
|
||||||
|
int backwardsPrev = data[backwards];
|
||||||
|
int forwardsPrev = data[forwards];
|
||||||
|
|
||||||
|
while (backwards > 0 || forwards < data.length-2) {
|
||||||
|
|
||||||
|
if (forwards < data.length-2) forwards++;
|
||||||
|
if (backwards > 0) backwards--;
|
||||||
|
|
||||||
|
if (backwardsPrev >= 0 && data[backwards] < 0) { // Found one!
|
||||||
|
return backwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forwardsPrev < 0 && data[forwards] >= 0) {
|
||||||
|
return forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
range--;
|
||||||
|
if (range == 0) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
backwardsPrev = data[backwards];
|
||||||
|
forwardsPrev = data[forwards];
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ public class Waveform extends JPanel {
|
|||||||
int leftMarker = 0;
|
int leftMarker = 0;
|
||||||
int rightMarker = 0;
|
int rightMarker = 0;
|
||||||
|
|
||||||
|
int leftAltMarker = 0;
|
||||||
|
int rightAltMarker = 0;
|
||||||
|
|
||||||
public Waveform() {
|
public Waveform() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@@ -87,15 +90,36 @@ public class Waveform extends JPanel {
|
|||||||
g.setColor(new Color(255, 0, 0));
|
g.setColor(new Color(255, 0, 0));
|
||||||
g.drawLine(leftMarker/step, 0, leftMarker/step, h);
|
g.drawLine(leftMarker/step, 0, leftMarker/step, h);
|
||||||
g.drawLine(rightMarker/step, 0, rightMarker/step, h);
|
g.drawLine(rightMarker/step, 0, rightMarker/step, h);
|
||||||
|
|
||||||
|
g.setColor(new Color(255, 255, 0));
|
||||||
|
|
||||||
|
g.drawLine(leftAltMarker/step, 0, leftAltMarker/step, h);
|
||||||
|
g.drawLine(rightAltMarker/step, 0, rightAltMarker/step, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAltMarkers(int l, int r) {
|
||||||
|
leftAltMarker = l;
|
||||||
|
rightAltMarker = r;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
public void setMarkers(int l, int r) {
|
public void setMarkers(int l, int r) {
|
||||||
leftMarker = l;
|
leftMarker = l;
|
||||||
rightMarker = r;
|
rightMarker = r;
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLeftAltMarker(int l) {
|
||||||
|
leftAltMarker = l;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRightAltMarker(int r) {
|
||||||
|
rightAltMarker = r;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
public void setLeftMarker(int l) {
|
public void setLeftMarker(int l) {
|
||||||
leftMarker = l;
|
leftMarker = l;
|
||||||
repaint();
|
repaint();
|
||||||
|
|||||||
Reference in New Issue
Block a user