Implement wheel over waveform to change gain

This commit is contained in:
2020-01-29 20:00:45 +00:00
parent bdbf4c604d
commit 38c6af7090
2 changed files with 106 additions and 35 deletions

View File

@@ -439,6 +439,16 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
} }
}); });
sampleWaveform.addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
if (selectedSentence == null) return;
if (selectedSentence.isLocked()) return;
int val = ((int)gainPercent.getValue()) - e.getWheelRotation();
if (val < 1) val = 1;
gainPercent.setValue(val);
}
});
sampleWaveform.addMarkerDragListener(new MarkerDragListener() { sampleWaveform.addMarkerDragListener(new MarkerDragListener() {
public void leftMarkerMoved(MarkerDragEvent e) { public void leftMarkerMoved(MarkerDragEvent e) {
Debug.trace(); Debug.trace();
@@ -474,7 +484,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace(); Debug.trace();
if (selectedSentence != null) { if (selectedSentence != null) {
selectedSentence.autoTrimSampleFFT(); selectedSentence.autoTrimSampleFFT();
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset()); sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing()); sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
postSentenceGap.setValue(selectedSentence.getPostGap()); postSentenceGap.setValue(selectedSentence.getPostGap());
@@ -488,7 +497,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace(); Debug.trace();
if (selectedSentence != null) { if (selectedSentence != null) {
selectedSentence.autoTrimSamplePeak(); selectedSentence.autoTrimSamplePeak();
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset()); sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing()); sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
postSentenceGap.setValue(selectedSentence.getPostGap()); postSentenceGap.setValue(selectedSentence.getPostGap());
@@ -502,7 +510,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace(); Debug.trace();
if (selectedSentence != null) { if (selectedSentence != null) {
selectedSentence.normalize(); selectedSentence.normalize();
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled)); gainPercent.setValue((int)(selectedSentence.getGain() * 100d));
updateWaveform(true);
} }
} }
}); });
@@ -550,7 +559,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
JSpinner ob = (JSpinner)e.getSource(); JSpinner ob = (JSpinner)e.getSource();
if (selectedSentence != null) { if (selectedSentence != null) {
selectedSentence.setGain((Integer)ob.getValue() / 100d); selectedSentence.setGain((Integer)ob.getValue() / 100d);
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled)); updateWaveform(true);
} }
} }
}); });
@@ -672,7 +681,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
KVPair<String, String> p = effectChain.getItemAt(i); KVPair<String, String> p = effectChain.getItemAt(i);
if (p == null) return; if (p == null) return;
selectedSentence.setEffectChain(p.getKey()); selectedSentence.setEffectChain(p.getKey());
updateWaveform(); updateWaveform(true);
} }
} }
}); });
@@ -2947,6 +2956,10 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
} }
public Sentence getRoomNoiseSentence() {
return roomNoise;
}
public byte[] getRoomNoise(int ms) { public byte[] getRoomNoise(int ms) {
Debug.trace(); Debug.trace();
@@ -3461,9 +3474,13 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
} }
public void updateWaveform() { public void updateWaveform() {
updateWaveform(false);
}
public void updateWaveform(boolean force) {
Debug.trace(); Debug.trace();
if (selectedSentence != null) { if (selectedSentence != null) {
if ((sampleWaveform.getId() != null) && (sampleWaveform.getId().equals(selectedSentence.getId()))) return; if ((!force) && (sampleWaveform.getId() != null) && (sampleWaveform.getId().equals(selectedSentence.getId()))) return;
sampleWaveform.setId(selectedSentence.getId()); sampleWaveform.setId(selectedSentence.getId());
if (rawAudio.isSelected()) { if (rawAudio.isSelected()) {
sampleWaveform.setData(selectedSentence.getRawAudioData()); sampleWaveform.setData(selectedSentence.getRawAudioData());
@@ -3796,17 +3813,17 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
KVPair<String, String> p = effectChain.getItemAt(i); KVPair<String, String> p = effectChain.getItemAt(i);
if (p.getKey().equals(key)) { if (p.getKey().equals(key)) {
effectChain.setSelectedIndex(i); effectChain.setSelectedIndex(i);
updateWaveform(); updateWaveform(true);
return; return;
} }
} }
if (effects.get(book.getDefaultEffect()) != null) { if (effects.get(book.getDefaultEffect()) != null) {
setEffectChain(book.getDefaultEffect()); setEffectChain(book.getDefaultEffect());
updateWaveform(); updateWaveform(true);
} else { } else {
effectChain.setSelectedIndex(0); effectChain.setSelectedIndex(0);
updateWaveform(); updateWaveform(true);
} }
} }
@@ -3874,12 +3891,14 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
int a = 0; int a = 0;
for (int i = 0; i < samples[Sentence.LEFT].length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
if ((i < start) || (i > end)) { if ((i < start) || (i > end)) {
croppedSamples[a++] = samples[i]; croppedSamples[Sentence.LEFT][a] = samples[Sentence.LEFT][i];
croppedSamples[Sentence.RIGHT][a] = samples[Sentence.RIGHT][i];
a++;
} }
} }
selectedSentence.writeAudioData(croppedSamples); selectedSentence.writeAudioData(croppedSamples);
selectedSentence.autoTrimSample(); selectedSentence.autoTrimSample();
updateWaveform(); updateWaveform(true);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -3906,9 +3925,13 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
for (int i = 0; i < samples[Sentence.LEFT].length; i++) { for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
if (i < at) { if (i < at) {
startSamples[a++] = samples[i]; startSamples[Sentence.LEFT][a] = samples[Sentence.LEFT][i];
startSamples[Sentence.RIGHT][a] = samples[Sentence.RIGHT][i];
a++;
} else { } else {
endSamples[b++] = samples[i]; endSamples[Sentence.LEFT][b] = samples[Sentence.LEFT][i];
endSamples[Sentence.RIGHT][b] = samples[Sentence.RIGHT][i];
b++;
} }
} }
@@ -3919,7 +3942,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
selectedSentence.writeAudioData(endSamples); selectedSentence.writeAudioData(endSamples);
selectedSentence.autoTrimSample(); selectedSentence.autoTrimSample();
newSentence.autoTrimSample(); newSentence.autoTrimSample();
updateWaveform(); updateWaveform(true);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} }

View File

@@ -86,6 +86,8 @@ public class Sentence extends BookTreeNode implements Cacheable {
double[][] processedAudio = null; double[][] processedAudio = null;
double[] fftProfile = null;
RecordingThread recordingThread; RecordingThread recordingThread;
boolean effectEthereal = false; boolean effectEthereal = false;
@@ -283,6 +285,17 @@ public class Sentence extends BookTreeNode implements Cacheable {
autoTrimSampleFFT(false); autoTrimSampleFFT(false);
} }
public double bucketDifference(double[] a, double[] b) {
double diff = 0d;
int l = Math.min(a.length, b.length);
for (int i = 0; i < l; i++) {
if ((a[i] - b[i]) > diff) {
diff = (a[i] - b[i]);
}
}
return diff;
}
public void autoTrimSampleFFT(boolean useRaw) { public void autoTrimSampleFFT(boolean useRaw) {
Debug.trace(); Debug.trace();
crossStartOffset = -1; crossStartOffset = -1;
@@ -297,11 +310,13 @@ public class Sentence extends BookTreeNode implements Cacheable {
return; return;
} }
double[] roomNoiseProfile = AudiobookRecorder.window.getRoomNoiseSentence().getFFTProfile();
int fftSize = Options.getInteger("audio.recording.trim.blocksize"); int fftSize = Options.getInteger("audio.recording.trim.blocksize");
int blocks = samples[LEFT].length / fftSize + 1; int blocks = samples[LEFT].length / fftSize + 1;
int[] intens = new int[blocks]; double[] intens = new double[blocks];
int block = 0; int block = 0;
for (int i = 0; i < samples[LEFT].length; i+= fftSize) { for (int i = 0; i < samples[LEFT].length; i+= fftSize) {
@@ -319,31 +334,20 @@ public class Sentence extends BookTreeNode implements Cacheable {
} }
double[] buckets = FFT.fft(real, imag, true); double[] buckets = FFT.fft(real, imag, true);
double av = 0;
for (int j = 1; j < fftSize/2; j++) {
av += Math.abs(buckets[j]);
}
av /= (fftSize / 2);
intens[block] = 0;
for (int j = 2; j < fftSize; j += 2) { intens[block] = bucketDifference(buckets, roomNoiseProfile);
double d = Math.abs(av - buckets[j]);
if (d > 0.05) {
intens[block]++;
}
}
block++; block++;
} }
int limit = Options.getInteger("audio.recording.trim.fft"); double limit = (double)(Options.getInteger("audio.recording.trim.fft"));
// Find first block with > 1 intensity and subtract one. // Find first block with > 1 intensity and subtract one.
int start = 0; int start = 0;
for (int i = 0; i < blocks; i++) { for (int i = 0; i < blocks; i++) {
if (intens[i] > limit) break; if (intens[i] >= (limit / 100.0)) break;
start = i; start = i;
} }
@@ -358,7 +362,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
int end = blocks - 1; int end = blocks - 1;
// And last block with > 1 intensity and add one. // And last block with > 1 intensity and add one.
for (int i = blocks-1; i >= 0; i--) { for (int i = blocks-1; i >= 0; i--) {
if (intens[i] > limit) break; if (intens[i] >= (limit / 100)) break;
end = i; end = i;
} }
@@ -380,6 +384,50 @@ public class Sentence extends BookTreeNode implements Cacheable {
reloadTree(); reloadTree();
} }
public double[] getFFTProfile() {
Debug.trace();
if (fftProfile != null) return fftProfile;
double[][] samples = getProcessedAudioData();
if (samples == null) {
return null;
}
int fftSize = Options.getInteger("audio.recording.trim.blocksize");
fftProfile = new double[fftSize / 2];
for (int j = 1; j < fftSize/2; j++) {
fftProfile[j] = 0d;
}
for (int i = 0; i < samples[LEFT].length; i+= fftSize) {
double[] real = new double[fftSize];
double[] imag = new double[fftSize];
for (int j = 0; j < fftSize; j++) {
if (i + j < samples[LEFT].length) {
real[j] = (samples[LEFT][i+j] + samples[RIGHT][i+j]) / 2d;
imag[j] = 0;
} else {
real[j] = 0;
imag[j] = 0;
}
}
double[] buckets = FFT.fft(real, imag, true);
for (int j = 1; j < fftSize/2; j++) {
fftProfile[j] += Math.abs(buckets[j]);
}
}
for (int j = 1; j < fftSize/2; j++) {
fftProfile[j] /= (double)(fftSize / 2d);
}
return fftProfile;
}
public void autoTrimSamplePeak() { public void autoTrimSamplePeak() {
Debug.trace(); Debug.trace();
autoTrimSamplePeak(false); autoTrimSamplePeak(false);
@@ -873,12 +921,12 @@ public class Sentence extends BookTreeNode implements Cacheable {
int gint = (int)(g * 100d); int gint = (int)(g * 100d);
int gainint = (int)(gain * 100d); int gainint = (int)(gain * 100d);
gain = g;
if (gint != gainint) { if (gint != gainint) {
CacheManager.removeFromCache(this); CacheManager.removeFromCache(this);
peak = -1; peak = -1;
reloadTree(); reloadTree();
} }
gain = g;
} }
public double getGain() { public double getGain() {
@@ -894,8 +942,8 @@ public class Sentence extends BookTreeNode implements Cacheable {
if (d > 1d) d = 1d; if (d > 1d) d = 1d;
if (d < low) d = low; if (d < low) d = low;
if (d > high) d = high; if (d > high) d = high;
peak = -1;
setGain(d); setGain(d);
peak = -1;
getPeak(); getPeak();
reloadTree(); reloadTree();
return d; return d;
@@ -945,7 +993,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
} catch (Exception e) { } catch (Exception e) {
} }
CacheManager.removeFromCache(Sentence.this); CacheManager.removeFromCache(Sentence.this);
AudiobookRecorder.window.updateWaveform(); AudiobookRecorder.window.updateWaveform(true);
} }
} }
@@ -1039,7 +1087,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
} }
CacheManager.removeFromCache(Sentence.this); CacheManager.removeFromCache(Sentence.this);
AudiobookRecorder.window.updateWaveform(); AudiobookRecorder.window.updateWaveform(true);
} }
} }
@@ -1084,7 +1132,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
} }
CacheManager.removeFromCache(this); CacheManager.removeFromCache(this);
AudiobookRecorder.window.updateWaveform(); AudiobookRecorder.window.updateWaveform(true);
} }
public double[][] getDoubleDataS16LE(AudioInputStream s, AudioFormat format) throws IOException { public double[][] getDoubleDataS16LE(AudioInputStream s, AudioFormat format) throws IOException {