1 /* 2 * Copyright (c) 2003, 2016, 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 java.io.File; 25 import java.util.Random; 26 27 import javax.sound.sampled.AudioFormat; 28 import javax.sound.sampled.AudioInputStream; 29 import javax.sound.sampled.AudioSystem; 30 import javax.sound.sampled.DataLine; 31 import javax.sound.sampled.LineUnavailableException; 32 import javax.sound.sampled.Mixer; 33 import javax.sound.sampled.SourceDataLine; 34 35 /** 36 * @test 37 * @bug 4828556 38 * @summary stopping and starting sampled audio plays small chunk in infinite 39 * loop 40 */ 41 public class StopStart implements Runnable { 42 43 static int sampleRate = 8000; 44 static double frequency = 2000.0; 45 static double RAD = 2.0 * Math.PI; 46 static Random random = new Random(); 47 48 static byte[] audioData = new byte[sampleRate/2]; 49 static SourceDataLine source; 50 51 static boolean terminated = false; 52 53 static int buffersWritten = 0; 54 static long bytesWritten = 0; 55 static int buffersWrittenAfter5Seconds; 56 57 static AudioInputStream ais = null; 58 static AudioFormat audioFormat; 59 static String filename; 60 61 static int executedTests=0; 62 static int successfulTests = 0; 63 64 public static void constructAIS() throws Exception { 65 ais = AudioSystem.getAudioInputStream(new File(filename)); 66 } 67 68 public static void doStartStopTest1() throws Exception { 69 System.out.println("TEST 1: play for 3 seconds, stop/start/stop/start/play for 3 seconds..."); 70 source.start(); 71 Thread.sleep(100); 72 bytesWritten = 0; 73 System.out.println("Waiting for 3 seconds..."); 74 Thread.sleep(3000); 75 buffersWrittenAfter5Seconds = buffersWritten; 76 System.out.println("Buffers Written: "+buffersWritten); 77 System.out.println("stop()->start()->stop()->start()"); 78 source.stop(); 79 //System.out.println("start()"); 80 source.start(); 81 //System.out.println("stop()2 ----------------------------------------------------------"); 82 source.stop(); 83 //System.out.println("start()"); 84 source.start(); 85 System.out.println("Buffers Written: "+buffersWritten); 86 System.out.println("Waiting for 3 seconds..."); 87 Thread.sleep(3000); 88 System.out.println("Buffers Written: "+buffersWritten); 89 if (buffersWritten >= ((buffersWrittenAfter5Seconds * 2) - ((buffersWrittenAfter5Seconds / 4)))) { 90 successfulTests++; 91 } 92 } 93 94 private static int nextWaitTime() { 95 int waitTime = random.nextInt(25); 96 waitTime*=waitTime; 97 if (waitTime<20) waitTime = 0; 98 return waitTime; 99 } 100 101 102 public static void doStartStopTest2() throws Exception { 103 System.out.println("TEST 2: start and stop 100 times with random wait in between"); 104 int max=100; 105 for (int i=0; i<max; i++) { 106 System.out.println("Round "+i); 107 System.out.println("Start...."); 108 source.start(); 109 int waitTime = nextWaitTime(); 110 System.out.println("Waiting for "+waitTime+"ms..."); 111 if (waitTime>0) { 112 Thread.sleep(waitTime); 113 } 114 System.out.println("stop()"); 115 source.stop(); 116 waitTime = nextWaitTime(); 117 System.out.println("Waiting for "+waitTime+"ms..."); 118 if (waitTime>0) { 119 Thread.sleep(waitTime); 120 } 121 } 122 } 123 124 public static void doStartStopTest3() throws Exception { 125 System.out.println("TEST 3: start and stop 100 times with random wait only every 10 rounds "); 126 int max=100; 127 for (int i=0; i<max; i++) { 128 System.out.println("Round "+i); 129 System.out.println("Start...."); 130 source.start(); 131 if (i % 10 == 9) { 132 int waitTime = nextWaitTime(); 133 System.out.println("Waiting for "+waitTime+"ms..."); 134 if (waitTime>0) { 135 Thread.sleep(waitTime); 136 } 137 } 138 System.out.println("stop()"); 139 source.stop(); 140 if (i % 13 == 12) { 141 int waitTime = nextWaitTime(); 142 System.out.println("Waiting for "+waitTime+"ms..."); 143 if (waitTime>0) { 144 Thread.sleep(waitTime); 145 } 146 } 147 } 148 } 149 150 public static void runTest(int testNum) { 151 terminated = false; 152 Thread thread = null; 153 buffersWrittenAfter5Seconds = 0; 154 // make the tests reproduceable by always seeding with same value 155 random.setSeed(1); 156 try { 157 executedTests++; 158 thread = new Thread(new StopStart()); 159 thread.start(); 160 switch (testNum) { 161 case 1: doStartStopTest1(); break; 162 case 2: doStartStopTest2(); break; 163 case 3: doStartStopTest3(); break; 164 } 165 } catch (Exception e) { 166 e.printStackTrace(); 167 } 168 source.stop(); 169 source.close(); 170 if (thread!=null) { 171 terminated = true; 172 System.out.println("Waiting for thread to die..."); 173 try { 174 thread.join(); 175 } catch (InterruptedException ie) { 176 ie.printStackTrace(); 177 } 178 } 179 } 180 181 public static void main(String[] args) throws Exception { 182 filename = null; 183 if (args.length>0) { 184 File f = new File(args[0]); 185 if (f.exists()) { 186 filename = args[0]; 187 System.out.println("Opening "+filename); 188 constructAIS(); 189 audioFormat = ais.getFormat(); 190 } 191 } 192 if (filename == null) { 193 audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true); 194 for (int i=0; i<audioData.length; i++) { 195 audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0); 196 } 197 } 198 long startTime = System.currentTimeMillis(); 199 Mixer.Info[] mixers = AudioSystem.getMixerInfo(); 200 for (int i=0; i<mixers.length; i++) { 201 try { 202 Mixer mixer = AudioSystem.getMixer(mixers[i]); 203 DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); 204 String mixerName = mixer.getMixerInfo().getName(); 205 try { 206 source = (SourceDataLine) mixer.getLine(info); 207 source.open(audioFormat); 208 } catch (IllegalArgumentException iae) { 209 System.out.println("Mixer "+mixerName+" does not provide a SourceDataLine."); 210 continue; 211 } catch (LineUnavailableException lue) { 212 System.out.println("Mixer "+mixerName+": no lines available."); 213 continue; 214 } 215 System.out.println("***** Testing on Mixer "+mixerName+":"); 216 //runTest(2); 217 //runTest(3); 218 runTest(1); 219 } catch (Exception e) { 220 e.printStackTrace(); 221 } 222 } 223 if (mixers.length==0) { 224 System.out.println("No mixers available!"); 225 } else { 226 long duration = System.currentTimeMillis() - startTime; 227 228 System.out.println("Test took "+(duration/1000)+"s and "+(duration % 1000)+"ms."); 229 } 230 231 System.out.println("Exiting main()"); 232 if (executedTests>0) { 233 if (successfulTests == 0) { 234 if (args.length == 0) { 235 throw new Exception("Test FAILED"); 236 } 237 System.out.println("test FAILED."); 238 } else { 239 System.out.println("test successful."); 240 } 241 } else { 242 System.out.println("Could not execute any tests - are soundcards correctly installed?"); 243 System.out.println("Test NOT FAILED."); 244 } 245 } 246 247 public void run() { 248 int len = audioData.length; 249 int offset = len; 250 System.out.println("Thread: started. Beginning audio i/o"); 251 while (!terminated) { 252 try { 253 //if (!source.isActive()) { 254 // Thread.sleep(50); 255 //} 256 if (offset >= len) { 257 offset = 0; 258 if (ais!=null) { 259 do { 260 len = ais.read(audioData, 0, audioData.length); 261 if (len < 0) { 262 constructAIS(); 263 } 264 } while (len < 0); 265 } 266 } 267 int toWrite = len - offset; 268 int written = source.write(audioData, offset, toWrite); 269 offset+=written; 270 bytesWritten += written; 271 buffersWritten = (int) (bytesWritten / audioData.length); 272 } catch (Exception e) { 273 e.printStackTrace(); 274 terminated = true; 275 } 276 } 277 System.out.println("Thread: closing line"); 278 source.stop(); 279 source.close(); 280 System.out.println("Thread finished"); 281 } 282 }