Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/javax/sound/sampled/DirectAudio/bug6372428.java
41153 views
1
/*
2
* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import javax.sound.sampled.AudioFormat;
25
import javax.sound.sampled.AudioSystem;
26
import javax.sound.sampled.DataLine;
27
import javax.sound.sampled.LineUnavailableException;
28
import javax.sound.sampled.SourceDataLine;
29
import javax.sound.sampled.TargetDataLine;
30
31
/*
32
* @test
33
* @bug 6372428
34
* @summary playback and capture doesn't interrupt after terminating thread that
35
* calls start()
36
* @run main bug6372428
37
*/
38
public class bug6372428 {
39
public bug6372428() {
40
}
41
42
public static void main(final String[] args) {
43
bug6372428 pThis = new bug6372428();
44
boolean failed1 = false;
45
boolean failed2 = false;
46
log("");
47
log("****************************************************************");
48
log("*** Playback Test");
49
log("****************************************************************");
50
log("");
51
try {
52
pThis.testPlayback();
53
} catch (IllegalArgumentException | LineUnavailableException e) {
54
System.out.println("Playback test is not applicable. Skipped");
55
} catch (Exception ex) {
56
ex.printStackTrace();
57
failed1 = true;
58
}
59
log("");
60
log("");
61
log("****************************************************************");
62
log("*** Capture Test");
63
log("****************************************************************");
64
log("");
65
try {
66
pThis.testRecord();
67
} catch (IllegalArgumentException | LineUnavailableException e) {
68
System.out.println("Record test is not applicable. Skipped");
69
} catch (Exception ex) {
70
ex.printStackTrace();
71
failed2 = true;
72
}
73
log("");
74
log("");
75
log("****************************************************************");
76
if (failed1 || failed2) {
77
String s = "";
78
if (failed1 && failed2)
79
s = "playback and capture";
80
else if (failed1)
81
s = "playback only";
82
else
83
s = "capture only";
84
throw new RuntimeException("Test FAILED (" + s + ")");
85
}
86
log("*** All tests passed successfully.");
87
}
88
89
final static int DATA_LENGTH = 15; // in seconds
90
final static int PLAYTHREAD_DELAY = 5; // in seconds
91
92
// playback test classes/routines
93
94
class PlayThread extends Thread {
95
SourceDataLine line;
96
public PlayThread(SourceDataLine line) {
97
this.line = line;
98
this.setDaemon(true);
99
}
100
101
public void run() {
102
log("PlayThread: starting...");
103
line.start();
104
log("PlayThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");
105
delay(PLAYTHREAD_DELAY * 1000);
106
log("PlayThread: exiting...");
107
}
108
}
109
110
class WriteThread extends Thread {
111
SourceDataLine line;
112
byte[] data;
113
volatile int remaining;
114
volatile boolean stopRequested = false;
115
public WriteThread(SourceDataLine line, byte[] data) {
116
this.line = line;
117
this.data = data;
118
remaining = data.length;
119
this.setDaemon(true);
120
}
121
122
public void run() {
123
while (remaining > 0 && !stopRequested) {
124
int avail = line.available();
125
if (avail > 0) {
126
if (avail > remaining)
127
avail = remaining;
128
int written = line.write(data, data.length - remaining, avail);
129
remaining -= written;
130
log("WriteThread: " + written + " bytes written");
131
} else {
132
delay(100);
133
}
134
}
135
if (remaining == 0) {
136
log("WriteThread: all data has been written, draining");
137
line.drain();
138
} else {
139
log("WriteThread: stop requested");
140
}
141
log("WriteThread: stopping");
142
line.stop();
143
log("WriteThread: exiting");
144
}
145
146
public boolean isCompleted() {
147
return (remaining <= 0);
148
}
149
150
public void requestStop() {
151
stopRequested = true;
152
}
153
}
154
155
void testPlayback() throws LineUnavailableException {
156
// prepare audio data
157
AudioFormat format = new AudioFormat(22050, 8, 1, false, false);
158
byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];
159
160
// create & open source data line
161
//SourceDataLine line = AudioSystem.getSourceDataLine(format);
162
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
163
SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
164
165
line.open(format);
166
167
// start write data thread
168
WriteThread p1 = new WriteThread(line, soundData);
169
p1.start();
170
171
// start line
172
PlayThread p2 = new PlayThread(line);
173
p2.start();
174
175
// monitor line
176
long lineTime1 = line.getMicrosecondPosition() / 1000;
177
long realTime1 = currentTimeMillis();
178
while (true) {
179
delay(500);
180
if (!line.isActive()) {
181
log("audio data played completely");
182
break;
183
}
184
long lineTime2 = line.getMicrosecondPosition() / 1000;
185
long realTime2 = currentTimeMillis();
186
long dLineTime = lineTime2 - lineTime1;
187
long dRealTime = realTime2 - realTime1;
188
log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));
189
if (dLineTime < 0) {
190
throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);
191
}
192
if (dRealTime < 450) {
193
// delay() has been interrupted?
194
continue;
195
}
196
lineTime1 = lineTime2;
197
realTime1 = realTime2;
198
}
199
}
200
201
202
// recording test classes/routines
203
204
class RecordThread extends Thread {
205
TargetDataLine line;
206
public RecordThread(TargetDataLine line) {
207
this.line = line;
208
this.setDaemon(true);
209
}
210
211
public void run() {
212
log("RecordThread: starting...");
213
line.start();
214
log("RecordThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");
215
delay(PLAYTHREAD_DELAY * 1000);
216
log("RecordThread: exiting...");
217
}
218
}
219
220
class ReadThread extends Thread {
221
TargetDataLine line;
222
byte[] data;
223
volatile int remaining;
224
public ReadThread(TargetDataLine line, byte[] data) {
225
this.line = line;
226
this.data = data;
227
remaining = data.length;
228
this.setDaemon(true);
229
}
230
231
public void run() {
232
log("ReadThread: buffer size is " + data.length + " bytes");
233
delay(200);
234
while ((remaining > 0) && line.isOpen()) {
235
int avail = line.available();
236
if (avail > 0) {
237
if (avail > remaining)
238
avail = remaining;
239
int read = line.read(data, data.length - remaining, avail);
240
remaining -= read;
241
log("ReadThread: " + read + " bytes read");
242
} else {
243
delay(100);
244
}
245
if (remaining <= 0) {
246
log("ReadThread: record buffer is full, exiting");
247
break;
248
}
249
}
250
if (remaining > 0) {
251
log("ReadThread: line has been stopped, exiting");
252
}
253
}
254
255
public int getCount() {
256
return data.length - remaining;
257
}
258
public boolean isCompleted() {
259
return (remaining <= 0);
260
}
261
}
262
263
void testRecord() throws LineUnavailableException {
264
// prepare audio data
265
AudioFormat format = new AudioFormat(22050, 8, 1, false, false);
266
267
// create & open target data line
268
//TargetDataLine line = AudioSystem.getTargetDataLine(format);
269
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
270
TargetDataLine line = (TargetDataLine)AudioSystem.getLine(info);
271
272
line.open(format);
273
274
// start read data thread
275
byte[] data = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];
276
ReadThread p1 = new ReadThread(line, data);
277
p1.start();
278
279
// start line
280
//new RecordThread(line).start();
281
RecordThread p2 = new RecordThread(line);
282
p2.start();
283
284
// monitor line
285
long endTime = currentTimeMillis() + DATA_LENGTH * 1000;
286
287
long realTime1 = currentTimeMillis();
288
long lineTime1 = line.getMicrosecondPosition() / 1000;
289
290
while (realTime1 < endTime && !p1.isCompleted()) {
291
delay(100);
292
long lineTime2 = line.getMicrosecondPosition() / 1000;
293
long realTime2 = currentTimeMillis();
294
long dLineTime = lineTime2 - lineTime1;
295
long dRealTime = realTime2 - realTime1;
296
log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));
297
if (dLineTime < 0) {
298
line.stop();
299
line.close();
300
throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);
301
}
302
if (dRealTime < 450) {
303
// delay() has been interrupted?
304
continue;
305
}
306
lineTime1 = lineTime2;
307
realTime1 = realTime2;
308
}
309
log("stopping line...");
310
line.stop();
311
line.close();
312
313
/*
314
log("");
315
log("");
316
log("");
317
log("recording completed, delaying 5 sec");
318
log("recorded " + p1.getCount() + " bytes, " + DATA_LENGTH + " seconds: " + (p1.getCount() * 8 / DATA_LENGTH) + " bit/sec");
319
log("");
320
log("");
321
log("");
322
delay(5000);
323
log("starting playing...");
324
playRecorded(format, data);
325
*/
326
}
327
328
void playRecorded(AudioFormat format, byte[] data) throws Exception {
329
//SourceDataLine line = AudioSystem.getSourceDataLine(format);
330
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
331
SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
332
333
line.open();
334
line.start();
335
336
int remaining = data.length;
337
while (remaining > 0) {
338
int avail = line.available();
339
if (avail > 0) {
340
if (avail > remaining)
341
avail = remaining;
342
int written = line.write(data, data.length - remaining, avail);
343
remaining -= written;
344
log("Playing: " + written + " bytes written");
345
} else {
346
delay(100);
347
}
348
}
349
350
line.drain();
351
line.stop();
352
}
353
354
// helper routines
355
static long startTime = currentTimeMillis();
356
static long currentTimeMillis() {
357
//return System.nanoTime() / 1000000L;
358
return System.currentTimeMillis();
359
}
360
static void log(String s) {
361
long time = currentTimeMillis() - startTime;
362
long ms = time % 1000;
363
time /= 1000;
364
long sec = time % 60;
365
time /= 60;
366
long min = time % 60;
367
time /= 60;
368
System.out.println(""
369
+ (time < 10 ? "0" : "") + time
370
+ ":" + (min < 10 ? "0" : "") + min
371
+ ":" + (sec < 10 ? "0" : "") + sec
372
+ "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
373
+ " (" + Thread.currentThread().getName() + ") " + s);
374
}
375
static void delay(int millis) {
376
try {
377
Thread.sleep(millis);
378
} catch (InterruptedException e) {}
379
}
380
}
381
382