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() {
public void leftMarkerMoved(MarkerDragEvent e) {
Debug.trace();
@@ -474,7 +484,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace();
if (selectedSentence != null) {
selectedSentence.autoTrimSampleFFT();
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
postSentenceGap.setValue(selectedSentence.getPostGap());
@@ -488,7 +497,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace();
if (selectedSentence != null) {
selectedSentence.autoTrimSamplePeak();
sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled));
sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset());
sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing());
postSentenceGap.setValue(selectedSentence.getPostGap());
@@ -502,7 +510,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace();
if (selectedSentence != null) {
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();
if (selectedSentence != null) {
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);
if (p == null) return;
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) {
Debug.trace();
@@ -3461,9 +3474,13 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
}
public void updateWaveform() {
updateWaveform(false);
}
public void updateWaveform(boolean force) {
Debug.trace();
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());
if (rawAudio.isSelected()) {
sampleWaveform.setData(selectedSentence.getRawAudioData());
@@ -3796,17 +3813,17 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
KVPair<String, String> p = effectChain.getItemAt(i);
if (p.getKey().equals(key)) {
effectChain.setSelectedIndex(i);
updateWaveform();
updateWaveform(true);
return;
}
}
if (effects.get(book.getDefaultEffect()) != null) {
setEffectChain(book.getDefaultEffect());
updateWaveform();
updateWaveform(true);
} else {
effectChain.setSelectedIndex(0);
updateWaveform();
updateWaveform(true);
}
}
@@ -3874,12 +3891,14 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
int a = 0;
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
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.autoTrimSample();
updateWaveform();
updateWaveform(true);
} catch (Exception ex) {
ex.printStackTrace();
}
@@ -3906,9 +3925,13 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
for (int i = 0; i < samples[Sentence.LEFT].length; i++) {
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 {
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.autoTrimSample();
newSentence.autoTrimSample();
updateWaveform();
updateWaveform(true);
} catch (Exception ex) {
ex.printStackTrace();
}

View File

@@ -86,6 +86,8 @@ public class Sentence extends BookTreeNode implements Cacheable {
double[][] processedAudio = null;
double[] fftProfile = null;
RecordingThread recordingThread;
boolean effectEthereal = false;
@@ -282,6 +284,17 @@ public class Sentence extends BookTreeNode implements Cacheable {
Debug.trace();
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) {
Debug.trace();
@@ -297,11 +310,13 @@ public class Sentence extends BookTreeNode implements Cacheable {
return;
}
double[] roomNoiseProfile = AudiobookRecorder.window.getRoomNoiseSentence().getFFTProfile();
int fftSize = Options.getInteger("audio.recording.trim.blocksize");
int blocks = samples[LEFT].length / fftSize + 1;
int[] intens = new int[blocks];
double[] intens = new double[blocks];
int block = 0;
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 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) {
double d = Math.abs(av - buckets[j]);
if (d > 0.05) {
intens[block]++;
}
}
intens[block] = bucketDifference(buckets, roomNoiseProfile);
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.
int start = 0;
for (int i = 0; i < blocks; i++) {
if (intens[i] > limit) break;
if (intens[i] >= (limit / 100.0)) break;
start = i;
}
@@ -358,7 +362,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
int end = blocks - 1;
// And last block with > 1 intensity and add one.
for (int i = blocks-1; i >= 0; i--) {
if (intens[i] > limit) break;
if (intens[i] >= (limit / 100)) break;
end = i;
}
@@ -380,6 +384,50 @@ public class Sentence extends BookTreeNode implements Cacheable {
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() {
Debug.trace();
autoTrimSamplePeak(false);
@@ -873,12 +921,12 @@ public class Sentence extends BookTreeNode implements Cacheable {
int gint = (int)(g * 100d);
int gainint = (int)(gain * 100d);
gain = g;
if (gint != gainint) {
CacheManager.removeFromCache(this);
peak = -1;
reloadTree();
}
gain = g;
}
public double getGain() {
@@ -894,8 +942,8 @@ public class Sentence extends BookTreeNode implements Cacheable {
if (d > 1d) d = 1d;
if (d < low) d = low;
if (d > high) d = high;
peak = -1;
setGain(d);
peak = -1;
getPeak();
reloadTree();
return d;
@@ -945,7 +993,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
} catch (Exception e) {
}
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);
AudiobookRecorder.window.updateWaveform();
AudiobookRecorder.window.updateWaveform(true);
}
}
@@ -1084,7 +1132,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
}
CacheManager.removeFromCache(this);
AudiobookRecorder.window.updateWaveform();
AudiobookRecorder.window.updateWaveform(true);
}
public double[][] getDoubleDataS16LE(AudioInputStream s, AudioFormat format) throws IOException {