Implement wheel over waveform to change gain
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -86,6 +86,8 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
||||
|
||||
double[][] processedAudio = null;
|
||||
|
||||
double[] fftProfile = null;
|
||||
|
||||
RecordingThread recordingThread;
|
||||
|
||||
boolean effectEthereal = false;
|
||||
@@ -283,6 +285,17 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
||||
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();
|
||||
crossStartOffset = -1;
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user