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 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.Mixer;
  29 import javax.sound.sampled.TargetDataLine;
  30 
  31 /**
  32  * @test
  33  * @bug 4836433
  34  * @summary Windows: TargetDataLine.flush() does not work. Since this test has
  35  *          some real-time variance, I disabled it by making it a manual test.
  36  * @run main/manual TargetDataLineFlush
  37  */
  38 public class TargetDataLineFlush {
  39     TargetDataLine inLine;
  40     int SAMPLE_RATE = 11025;
  41     int BUFFER_MILLIS = 1000;
  42     int WAIT_MILLIS;
  43     int BITS = 16;
  44     int CHANNELS = 2;
  45     int bufferSize;
  46     AudioFormat format;
  47     Mixer.Info[] mixers;
  48     static boolean failed = false;
  49 
  50     public TargetDataLineFlush() {
  51         mixers = AudioSystem.getMixerInfo();
  52     }
  53 
  54     private void init() {
  55         // float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian
  56         format = new AudioFormat( (float) SAMPLE_RATE, BITS, CHANNELS, true, false);
  57         bufferSize = SAMPLE_RATE * BUFFER_MILLIS / 1000 * format.getFrameSize();
  58     }
  59 
  60     boolean openInputLine(int num)  throws LineUnavailableException {
  61         init();
  62         DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); // format is an AudioFormat object
  63         // Obtain and open a outLine.
  64         if (num < 0) {
  65             if (!AudioSystem.isLineSupported(info)) {
  66                 System.out.println("TargetDataLine is not supported by default mixer.");
  67                 return false;
  68             }
  69             inLine = (TargetDataLine) AudioSystem.getLine(info);
  70         } else {
  71             Mixer mixer = AudioSystem.getMixer(mixers[num]);
  72             if (!mixer.isLineSupported(info)) {
  73                 System.out.println("TargetDataLine is not supported by this mixer.");
  74                 return false;
  75             }
  76             inLine = (TargetDataLine) mixer.getLine(info);
  77         }
  78         inLine.open(format, bufferSize);
  79         /*if (Math.abs(inLine.getBufferSize() - bufferSize) > 100) {
  80                 inLine.close();
  81                 System.out.println("TargetDataLine does not support buffer size of "+bufferSize+" bytes!");
  82                 return false;
  83         }*/
  84         bufferSize = inLine.getBufferSize();
  85         /* 3/4 of buffer size ot wait */
  86         WAIT_MILLIS = (int) (bufferSize / format.getFrameSize() * 750 / format.getFrameRate());
  87         System.out.println("Buffer size: "+bufferSize+" bytes = "
  88             +((int) (bufferSize / format.getFrameSize() * 750 / format.getFrameRate()))+" millis");
  89         return true;
  90     }
  91 
  92     private String available() {
  93         int avail = inLine.available();
  94         int availMillis = (int) (avail / format.getFrameSize() * 1000 / format.getFrameRate());
  95         return "available "+avail+" bytes = "+availMillis+" millis";
  96     }
  97 
  98     private boolean recordSound(int num)  throws LineUnavailableException {
  99         if (!openInputLine(num)) {
 100             return false;
 101         }
 102         byte data[] = new byte[1000];
 103         try {
 104             System.out.println("Got line: "+inLine);
 105             System.out.println("Start recording" );
 106             inLine.start();
 107             System.out.print("Warm-up...");
 108             //System.out.print("Waiting 500 millis...");
 109             try { Thread.sleep(500); } catch (InterruptedException ie) {}
 110             //System.out.println("done. "+available());
 111             //System.out.print("Reading all data...");
 112             int avail0 = inLine.available();
 113             if (avail0 == 0) {
 114                 System.out.println("Problem: TargetDataLine did not deliver any data!");
 115                 System.out.println("Not a test failure, but serious failure nonetheless.");
 116             } else {
 117                 while ((avail0 -= inLine.read(data, 0, Math.min(data.length, avail0))) > 0);
 118                 System.out.println("done.  "+available());
 119                 System.out.print("Waiting "+(WAIT_MILLIS)+" millis...");
 120                 try { Thread.sleep(WAIT_MILLIS); } catch (InterruptedException ie) {}
 121                 int avail1 = inLine.available();
 122                 System.out.println("done. "+available());
 123 
 124                 System.out.print("Flushing...");
 125                 inLine.flush();
 126                 System.out.println("done.            "+available());
 127                 System.out.print("Waiting "+(WAIT_MILLIS)+" millis...");
 128                 try { Thread.sleep(WAIT_MILLIS); } catch (InterruptedException ie) {}
 129                 int avail2 = inLine.available();
 130                 System.out.println("done.  "+available());
 131                 if (avail2 > avail1) {
 132                     failed = true;
 133                     System.out.println("Failed: Flushing with native flush() should "
 134                                        +"result in fewer bytes available.");
 135                 }
 136                 if (avail2 == 0) {
 137                     failed = true;
 138                     System.out.println("Failed: Recording after flush() did not work at all!");
 139                 }
 140             }
 141         } finally {
 142             System.out.print("Closing line....");
 143             inLine.close();
 144             System.out.println("done");
 145         }
 146         return true;
 147     }
 148 
 149     public void runTests(int testRuns) {
 150         if (mixers.length > 0) {
 151             for (int num = -1; num < mixers.length; num++) {
 152                 try {
 153                     if (num<0) {
 154                         System.out.println("------Using default line...." );
 155                     } else {
 156                         System.out.println("------Using line "+num+" from mixer "+mixers[num]+"...");
 157                     }
 158                     for (int testRun = 0; testRun < testRuns; testRun++) {
 159                         if (testRuns>1) {
 160                             System.out.println("--Run "+(testRun+1)+"/"+testRuns+":");
 161                         }
 162                         if (!recordSound(num)) {
 163                             break;
 164                         }
 165                     }
 166                 } catch (Exception ex) {
 167                     System.out.println("Caught " + ex );
 168                 }
 169                 System.out.println("------------------------------------------------------");
 170                 if (failed) {
 171                     break;
 172                 }
 173             }
 174         } else {
 175             System.out.println("No mixers present. Cannot execute this test.");
 176         }
 177     }
 178 
 179 
 180     public static void main(String[] args) throws Exception {
 181         System.out.println("Test TargetDataLineFlush");
 182         System.out.println("This verifies that TargetDataLine.flush() actually");
 183         System.out.println("flushes the native buffers. This is done by");
 184         System.out.println("comparing a manual flush (i.e. just discarding");
 185         System.out.println("everything that is currently available in the TargetDataLine)");
 186         System.out.println("to a flushed line");
 187         TargetDataLineFlush app = new TargetDataLineFlush();
 188         int testRuns = 1;
 189         if (args.length > 0) {
 190             try {
 191                 testRuns = Integer.parseInt(args[0]);
 192             } catch (NumberFormatException nfe) {
 193                 System.out.println("Usage: java TargetDataLineFlush [number of runs]");
 194                 System.out.println("Parameters ignored.");
 195             }
 196         }
 197         app.runTests(testRuns);
 198         if (failed) {
 199             throw new Exception("Test FAILED");
 200         }
 201         // test always passes if it gets here
 202         System.out.println("Test PASSED");
 203     }
 204 }