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