Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/sound/sampled/DirectAudio/bug6372428.java
38855 views
/*1* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import javax.sound.sampled.AudioFormat;24import javax.sound.sampled.AudioSystem;25import javax.sound.sampled.DataLine;26import javax.sound.sampled.LineUnavailableException;27import javax.sound.sampled.SourceDataLine;28import javax.sound.sampled.TargetDataLine;2930/*31* @test32* @bug 637242833* @summary playback and capture doesn't interrupt after terminating thread that34* calls start()35* @run main bug637242836* @key headful37*/38public class bug6372428 {39public bug6372428() {40}4142public static void main(final String[] args) {43bug6372428 pThis = new bug6372428();44boolean failed1 = false;45boolean failed2 = false;46log("");47log("****************************************************************");48log("*** Playback Test");49log("****************************************************************");50log("");51try {52pThis.testPlayback();53} catch (IllegalArgumentException | LineUnavailableException e) {54System.out.println("Playback test is not applicable. Skipped");55} catch (Exception ex) {56ex.printStackTrace();57failed1 = true;58}59log("");60log("");61log("****************************************************************");62log("*** Capture Test");63log("****************************************************************");64log("");65try {66pThis.testRecord();67} catch (IllegalArgumentException | LineUnavailableException e) {68System.out.println("Record test is not applicable. Skipped");69} catch (Exception ex) {70ex.printStackTrace();71failed2 = true;72}73log("");74log("");75log("****************************************************************");76if (failed1 || failed2) {77String s = "";78if (failed1 && failed2)79s = "playback and capture";80else if (failed1)81s = "playback only";82else83s = "capture only";84throw new RuntimeException("Test FAILED (" + s + ")");85}86log("*** All tests passed successfully.");87}8889final static int DATA_LENGTH = 15; // in seconds90final static int PLAYTHREAD_DELAY = 5; // in seconds9192// playback test classes/routines9394class PlayThread extends Thread {95SourceDataLine line;96public PlayThread(SourceDataLine line) {97this.line = line;98this.setDaemon(true);99}100101public void run() {102log("PlayThread: starting...");103line.start();104log("PlayThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");105delay(PLAYTHREAD_DELAY * 1000);106log("PlayThread: exiting...");107}108}109110class WriteThread extends Thread {111SourceDataLine line;112byte[] data;113volatile int remaining;114volatile boolean stopRequested = false;115public WriteThread(SourceDataLine line, byte[] data) {116this.line = line;117this.data = data;118remaining = data.length;119this.setDaemon(true);120}121122public void run() {123while (remaining > 0 && !stopRequested) {124int avail = line.available();125if (avail > 0) {126if (avail > remaining)127avail = remaining;128int written = line.write(data, data.length - remaining, avail);129remaining -= written;130log("WriteThread: " + written + " bytes written");131} else {132delay(100);133}134}135if (remaining == 0) {136log("WriteThread: all data has been written, draining");137line.drain();138} else {139log("WriteThread: stop requested");140}141log("WriteThread: stopping");142line.stop();143log("WriteThread: exiting");144}145146public boolean isCompleted() {147return (remaining <= 0);148}149150public void requestStop() {151stopRequested = true;152}153}154155void testPlayback() throws LineUnavailableException {156// prepare audio data157AudioFormat format = new AudioFormat(22050, 8, 1, false, false);158byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];159160// create & open source data line161//SourceDataLine line = AudioSystem.getSourceDataLine(format);162DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);163SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);164165line.open(format);166167// start write data thread168WriteThread p1 = new WriteThread(line, soundData);169p1.start();170171// start line172PlayThread p2 = new PlayThread(line);173p2.start();174175// monitor line176long lineTime1 = line.getMicrosecondPosition() / 1000;177long realTime1 = currentTimeMillis();178while (true) {179delay(500);180if (!line.isActive()) {181log("audio data played completely");182break;183}184long lineTime2 = line.getMicrosecondPosition() / 1000;185long realTime2 = currentTimeMillis();186long dLineTime = lineTime2 - lineTime1;187long dRealTime = realTime2 - realTime1;188log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));189if (dLineTime < 0) {190throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);191}192if (dRealTime < 450) {193// delay() has been interrupted?194continue;195}196lineTime1 = lineTime2;197realTime1 = realTime2;198}199}200201202// recording test classes/routines203204class RecordThread extends Thread {205TargetDataLine line;206public RecordThread(TargetDataLine line) {207this.line = line;208this.setDaemon(true);209}210211public void run() {212log("RecordThread: starting...");213line.start();214log("RecordThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");215delay(PLAYTHREAD_DELAY * 1000);216log("RecordThread: exiting...");217}218}219220class ReadThread extends Thread {221TargetDataLine line;222byte[] data;223volatile int remaining;224public ReadThread(TargetDataLine line, byte[] data) {225this.line = line;226this.data = data;227remaining = data.length;228this.setDaemon(true);229}230231public void run() {232log("ReadThread: buffer size is " + data.length + " bytes");233delay(200);234while ((remaining > 0) && line.isOpen()) {235int avail = line.available();236if (avail > 0) {237if (avail > remaining)238avail = remaining;239int read = line.read(data, data.length - remaining, avail);240remaining -= read;241log("ReadThread: " + read + " bytes read");242} else {243delay(100);244}245if (remaining <= 0) {246log("ReadThread: record buffer is full, exiting");247break;248}249}250if (remaining > 0) {251log("ReadThread: line has been stopped, exiting");252}253}254255public int getCount() {256return data.length - remaining;257}258public boolean isCompleted() {259return (remaining <= 0);260}261}262263void testRecord() throws LineUnavailableException {264// prepare audio data265AudioFormat format = new AudioFormat(22050, 8, 1, false, false);266267// create & open target data line268//TargetDataLine line = AudioSystem.getTargetDataLine(format);269DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);270TargetDataLine line = (TargetDataLine)AudioSystem.getLine(info);271272line.open(format);273274// start read data thread275byte[] data = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];276ReadThread p1 = new ReadThread(line, data);277p1.start();278279// start line280//new RecordThread(line).start();281RecordThread p2 = new RecordThread(line);282p2.start();283284// monitor line285long endTime = currentTimeMillis() + DATA_LENGTH * 1000;286287long realTime1 = currentTimeMillis();288long lineTime1 = line.getMicrosecondPosition() / 1000;289290while (realTime1 < endTime && !p1.isCompleted()) {291delay(100);292long lineTime2 = line.getMicrosecondPosition() / 1000;293long realTime2 = currentTimeMillis();294long dLineTime = lineTime2 - lineTime1;295long dRealTime = realTime2 - realTime1;296log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));297if (dLineTime < 0) {298line.stop();299line.close();300throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);301}302if (dRealTime < 450) {303// delay() has been interrupted?304continue;305}306lineTime1 = lineTime2;307realTime1 = realTime2;308}309log("stopping line...");310line.stop();311line.close();312313/*314log("");315log("");316log("");317log("recording completed, delaying 5 sec");318log("recorded " + p1.getCount() + " bytes, " + DATA_LENGTH + " seconds: " + (p1.getCount() * 8 / DATA_LENGTH) + " bit/sec");319log("");320log("");321log("");322delay(5000);323log("starting playing...");324playRecorded(format, data);325*/326}327328void playRecorded(AudioFormat format, byte[] data) throws Exception {329//SourceDataLine line = AudioSystem.getSourceDataLine(format);330DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);331SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);332333line.open();334line.start();335336int remaining = data.length;337while (remaining > 0) {338int avail = line.available();339if (avail > 0) {340if (avail > remaining)341avail = remaining;342int written = line.write(data, data.length - remaining, avail);343remaining -= written;344log("Playing: " + written + " bytes written");345} else {346delay(100);347}348}349350line.drain();351line.stop();352}353354// helper routines355static long startTime = currentTimeMillis();356static long currentTimeMillis() {357//return System.nanoTime() / 1000000L;358return System.currentTimeMillis();359}360static void log(String s) {361long time = currentTimeMillis() - startTime;362long ms = time % 1000;363time /= 1000;364long sec = time % 60;365time /= 60;366long min = time % 60;367time /= 60;368System.out.println(""369+ (time < 10 ? "0" : "") + time370+ ":" + (min < 10 ? "0" : "") + min371+ ":" + (sec < 10 ? "0" : "") + sec372+ "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms373+ " (" + Thread.currentThread().getName() + ") " + s);374}375static void delay(int millis) {376try {377Thread.sleep(millis);378} catch (InterruptedException e) {}379}380}381382383