Skip to content

Commit bf9ff1a

Browse files
committed
Adjust ShowRealTimeSpectrumApp in spectrum analyzer:
- targetDataLine.start() вызывается один раз перед циклом, stop()/close() — в finally, чтобы линия всегда освобождалась - Закрытие окна — displayChart() возвращает JFrame; на него вешается WindowListener: в windowClosing выставляется capturing=false и вызывается targetDataLine.stop(), чтобы разблокировать поток, заблокированный на read - ByteArrayOutputStream убран: на каждой итерации и так был один фрагмент — используется Arrays.copyOf(tempBuffer, count) - Цикл while (capturing.get()) вместо бесконечного while (true)
1 parent 59e42ad commit bf9ff1a

1 file changed

Lines changed: 48 additions & 31 deletions

File tree

sound-recorder-n-spectrum-analyzer/src/main/java/by/andd3dfx/capturesound/ShowRealTimeSpectrumApp.java

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
import javax.sound.sampled.DataLine;
1212
import javax.sound.sampled.LineUnavailableException;
1313
import javax.sound.sampled.TargetDataLine;
14-
import java.io.ByteArrayOutputStream;
14+
import javax.swing.JFrame;
15+
import javax.swing.WindowConstants;
16+
import java.awt.event.WindowAdapter;
17+
import java.awt.event.WindowEvent;
1518
import java.util.Arrays;
19+
import java.util.concurrent.atomic.AtomicBoolean;
1620

1721
/**
1822
* Application that shows real-time spectrum of sound
@@ -28,45 +32,58 @@ public static void main(String[] args) throws LineUnavailableException {
2832
AudioFormat audioFormat = buildAudioFormat();
2933
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
3034

31-
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
3235
TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
3336
targetDataLine.open(audioFormat);
3437

3538
ChartContainer chartContainer = new ChartContainer();
36-
chartContainer.show();
39+
JFrame chartFrame = chartContainer.show();
40+
chartFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
41+
42+
AtomicBoolean capturing = new AtomicBoolean(true);
43+
chartFrame.addWindowListener(new WindowAdapter() {
44+
@Override
45+
public void windowClosing(WindowEvent e) {
46+
capturing.set(false);
47+
targetDataLine.stop();
48+
}
49+
});
3750

3851
byte tempBuffer[] = new byte[10_000];
3952
double[] xData = new double[BUCKETS_AMOUNT];
4053
double[] yData = new double[BUCKETS_AMOUNT];
41-
while (true) {
42-
targetDataLine.start();
43-
int count = targetDataLine.read(tempBuffer, 0, tempBuffer.length);
44-
if (count > 0) {
45-
byteArrayOutputStream.write(tempBuffer, 0, count);
46-
}
47-
byte audioData[] = byteArrayOutputStream.toByteArray();
48-
targetDataLine.stop();
49-
byteArrayOutputStream.reset();
50-
51-
FrequencyInfoContainer frequencyInfoContainer = frequencyScanner.detectFrequency(audioData, (int) audioFormat.getSampleRate());
52-
double[] frequencies = frequencyInfoContainer.frequencies();
53-
double[] magnitudes = frequencyInfoContainer.magnitudes();
54-
55-
Arrays.fill(xData, 0);
56-
Arrays.fill(yData, 0);
57-
final int magnitudesPerBucket = magnitudes.length / BUCKETS_AMOUNT;
58-
for (int bucket = 0; bucket < BUCKETS_AMOUNT; bucket++) {
59-
xData[bucket] = frequencies[(int) ((bucket + 0.5) * magnitudesPerBucket)];
60-
61-
for (int i = 0; i < magnitudesPerBucket; i++) {
62-
yData[bucket] += magnitudes[bucket * magnitudesPerBucket + i];
54+
targetDataLine.start();
55+
try {
56+
while (capturing.get()) {
57+
int count = targetDataLine.read(tempBuffer, 0, tempBuffer.length);
58+
if (count <= 0) {
59+
continue;
60+
}
61+
byte[] audioData = Arrays.copyOf(tempBuffer, count);
62+
63+
FrequencyInfoContainer frequencyInfoContainer =
64+
frequencyScanner.detectFrequency(audioData, (int) audioFormat.getSampleRate());
65+
double[] frequencies = frequencyInfoContainer.frequencies();
66+
double[] magnitudes = frequencyInfoContainer.magnitudes();
67+
68+
Arrays.fill(xData, 0);
69+
Arrays.fill(yData, 0);
70+
final int magnitudesPerBucket = magnitudes.length / BUCKETS_AMOUNT;
71+
for (int bucket = 0; bucket < BUCKETS_AMOUNT; bucket++) {
72+
xData[bucket] = frequencies[(int) ((bucket + 0.5) * magnitudesPerBucket)];
73+
74+
for (int i = 0; i < magnitudesPerBucket; i++) {
75+
yData[bucket] += magnitudes[bucket * magnitudesPerBucket + i];
76+
}
6377
}
64-
}
6578

66-
var maxFrequency = frequencyInfoContainer.maxFrequency();
67-
String title = String.format("%1$.0f Hz", maxFrequency);
79+
var maxFrequency = frequencyInfoContainer.maxFrequency();
80+
String title = String.format("%1$.0f Hz", maxFrequency);
6881

69-
chartContainer.update(xData, yData, title);
82+
chartContainer.update(xData, yData, title);
83+
}
84+
} finally {
85+
targetDataLine.stop();
86+
targetDataLine.close();
7087
}
7188
}
7289

@@ -85,9 +102,9 @@ public ChartContainer() {
85102
chart.getStyler().setXAxisLogarithmic(true);
86103
}
87104

88-
public void show() {
105+
public JFrame show() {
89106
chartSwingWrapper = new SwingWrapper<>(chart);
90-
chartSwingWrapper.displayChart();
107+
return chartSwingWrapper.displayChart();
91108
}
92109

93110
public void update(double[] xData, double[] yData, String title) {

0 commit comments

Comments
 (0)