blob: 1eec9d6b6742b37853fff5e44ee83e5982cb8b64 [file] [log] [blame]
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.util.Random;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
/**
* @test
* @bug 4828556
* @summary stopping and starting sampled audio plays small chunk in infinite
* loop
*/
public class StopStart implements Runnable {
static int sampleRate = 8000;
static double frequency = 2000.0;
static double RAD = 2.0 * Math.PI;
static Random random = new Random();
static byte[] audioData = new byte[sampleRate/2];
static SourceDataLine source;
static boolean terminated = false;
static int buffersWritten = 0;
static long bytesWritten = 0;
static int buffersWrittenAfter5Seconds;
static AudioInputStream ais = null;
static AudioFormat audioFormat;
static String filename;
static int executedTests=0;
static int successfulTests = 0;
public static void constructAIS() throws Exception {
ais = AudioSystem.getAudioInputStream(new File(filename));
}
public static void doStartStopTest1() throws Exception {
System.out.println("TEST 1: play for 3 seconds, stop/start/stop/start/play for 3 seconds...");
source.start();
Thread.sleep(100);
bytesWritten = 0;
System.out.println("Waiting for 3 seconds...");
Thread.sleep(3000);
buffersWrittenAfter5Seconds = buffersWritten;
System.out.println("Buffers Written: "+buffersWritten);
System.out.println("stop()->start()->stop()->start()");
source.stop();
//System.out.println("start()");
source.start();
//System.out.println("stop()2 ----------------------------------------------------------");
source.stop();
//System.out.println("start()");
source.start();
System.out.println("Buffers Written: "+buffersWritten);
System.out.println("Waiting for 3 seconds...");
Thread.sleep(3000);
System.out.println("Buffers Written: "+buffersWritten);
if (buffersWritten >= ((buffersWrittenAfter5Seconds * 2) - ((buffersWrittenAfter5Seconds / 4)))) {
successfulTests++;
}
}
private static int nextWaitTime() {
int waitTime = random.nextInt(25);
waitTime*=waitTime;
if (waitTime<20) waitTime = 0;
return waitTime;
}
public static void doStartStopTest2() throws Exception {
System.out.println("TEST 2: start and stop 100 times with random wait in between");
int max=100;
for (int i=0; i<max; i++) {
System.out.println("Round "+i);
System.out.println("Start....");
source.start();
int waitTime = nextWaitTime();
System.out.println("Waiting for "+waitTime+"ms...");
if (waitTime>0) {
Thread.sleep(waitTime);
}
System.out.println("stop()");
source.stop();
waitTime = nextWaitTime();
System.out.println("Waiting for "+waitTime+"ms...");
if (waitTime>0) {
Thread.sleep(waitTime);
}
}
}
public static void doStartStopTest3() throws Exception {
System.out.println("TEST 3: start and stop 100 times with random wait only every 10 rounds ");
int max=100;
for (int i=0; i<max; i++) {
System.out.println("Round "+i);
System.out.println("Start....");
source.start();
if (i % 10 == 9) {
int waitTime = nextWaitTime();
System.out.println("Waiting for "+waitTime+"ms...");
if (waitTime>0) {
Thread.sleep(waitTime);
}
}
System.out.println("stop()");
source.stop();
if (i % 13 == 12) {
int waitTime = nextWaitTime();
System.out.println("Waiting for "+waitTime+"ms...");
if (waitTime>0) {
Thread.sleep(waitTime);
}
}
}
}
public static void runTest(int testNum) {
terminated = false;
Thread thread = null;
buffersWrittenAfter5Seconds = 0;
// make the tests reproduceable by always seeding with same value
random.setSeed(1);
try {
executedTests++;
thread = new Thread(new StopStart());
thread.start();
switch (testNum) {
case 1: doStartStopTest1(); break;
case 2: doStartStopTest2(); break;
case 3: doStartStopTest3(); break;
}
} catch (Exception e) {
e.printStackTrace();
}
source.stop();
source.close();
if (thread!=null) {
terminated = true;
System.out.println("Waiting for thread to die...");
try {
thread.join();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
filename = null;
if (args.length>0) {
File f = new File(args[0]);
if (f.exists()) {
filename = args[0];
System.out.println("Opening "+filename);
constructAIS();
audioFormat = ais.getFormat();
}
}
if (filename == null) {
audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true);
for (int i=0; i<audioData.length; i++) {
audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0);
}
}
long startTime = System.currentTimeMillis();
Mixer.Info[] mixers = AudioSystem.getMixerInfo();
for (int i=0; i<mixers.length; i++) {
try {
Mixer mixer = AudioSystem.getMixer(mixers[i]);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
String mixerName = mixer.getMixerInfo().getName();
try {
source = (SourceDataLine) mixer.getLine(info);
source.open(audioFormat);
} catch (IllegalArgumentException iae) {
System.out.println("Mixer "+mixerName+" does not provide a SourceDataLine.");
continue;
} catch (LineUnavailableException lue) {
System.out.println("Mixer "+mixerName+": no lines available.");
continue;
}
System.out.println("***** Testing on Mixer "+mixerName+":");
//runTest(2);
//runTest(3);
runTest(1);
} catch (Exception e) {
e.printStackTrace();
}
}
if (mixers.length==0) {
System.out.println("No mixers available!");
} else {
long duration = System.currentTimeMillis() - startTime;
System.out.println("Test took "+(duration/1000)+"s and "+(duration % 1000)+"ms.");
}
System.out.println("Exiting main()");
if (executedTests>0) {
if (successfulTests == 0) {
if (args.length == 0) {
throw new Exception("Test FAILED");
}
System.out.println("test FAILED.");
} else {
System.out.println("test successful.");
}
} else {
System.out.println("Could not execute any tests - are soundcards correctly installed?");
System.out.println("Test NOT FAILED.");
}
}
public void run() {
int len = audioData.length;
int offset = len;
System.out.println("Thread: started. Beginning audio i/o");
while (!terminated) {
try {
//if (!source.isActive()) {
// Thread.sleep(50);
//}
if (offset >= len) {
offset = 0;
if (ais!=null) {
do {
len = ais.read(audioData, 0, audioData.length);
if (len < 0) {
constructAIS();
}
} while (len < 0);
}
}
int toWrite = len - offset;
int written = source.write(audioData, offset, toWrite);
offset+=written;
bytesWritten += written;
buffersWritten = (int) (bytesWritten / audioData.length);
} catch (Exception e) {
e.printStackTrace();
terminated = true;
}
}
System.out.println("Thread: closing line");
source.stop();
source.close();
System.out.println("Thread finished");
}
}