1 /*
   2  * Copyright (c) 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.ByteArrayInputStream;
  25 import java.io.ByteArrayOutputStream;
  26 import java.io.IOException;
  27 import java.io.InputStream;
  28 import java.util.ArrayList;
  29 import java.util.List;
  30 
  31 import javax.sound.sampled.AudioFileFormat;
  32 import javax.sound.sampled.AudioFormat;
  33 import javax.sound.sampled.AudioInputStream;
  34 import javax.sound.sampled.AudioSystem;
  35 import javax.sound.sampled.UnsupportedAudioFileException;
  36 import javax.sound.sampled.spi.AudioFileWriter;
  37 import javax.sound.sampled.spi.FormatConversionProvider;
  38 
  39 import static java.util.ServiceLoader.load;
  40 import static javax.sound.sampled.AudioFileFormat.Type.AIFC;
  41 import static javax.sound.sampled.AudioFileFormat.Type.AIFF;
  42 import static javax.sound.sampled.AudioFileFormat.Type.AU;
  43 import static javax.sound.sampled.AudioFileFormat.Type.SND;
  44 import static javax.sound.sampled.AudioFileFormat.Type.WAVE;
  45 import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED;
  46 
  47 /**
  48  * @test
  49  * @bug 8038139
  50  */
  51 public final class FrameLengthAfterConversion {
  52 
  53     /**
  54      * We will try to use all formats, in this case all our providers will be
  55      * covered by supported/unsupported formats.
  56      */
  57     private static final List<AudioFormat> formats = new ArrayList<>(23000);
  58 
  59     private static final AudioFormat.Encoding[] encodings = {
  60             AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW,
  61             AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED,
  62             AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test")
  63     };
  64 
  65     private static final int[] sampleBits = {
  66             1, 4, 8, 11, 16, 20, 24, 32, 48, 64, 128
  67     };
  68 
  69     private static final int[] channels = {
  70             1, 2, 3, 4, 5, 6, 7, 8, 9, 10
  71     };
  72 
  73     private static final AudioFileFormat.Type[] types = {
  74             WAVE, AU, AIFF, AIFC, SND,
  75             new AudioFileFormat.Type("TestName", "TestExt")
  76     };
  77 
  78     private static final int FRAME_LENGTH = 10;
  79 
  80     static {
  81         for (final int sampleSize : sampleBits) {
  82             for (final int channel : channels) {
  83                 for (final AudioFormat.Encoding enc : encodings) {
  84                     final int frameSize = ((sampleSize + 7) / 8) * channel;
  85                     formats.add(new AudioFormat(enc, 44100, sampleSize, channel,
  86                                                 frameSize, 44100, true));
  87                     formats.add(new AudioFormat(enc, 44100, sampleSize, channel,
  88                                                 frameSize, 44100, false));
  89                 }
  90             }
  91         }
  92     }
  93 
  94     public static void main(final String[] args) {
  95         for (final FormatConversionProvider fcp : load(
  96                 FormatConversionProvider.class)) {
  97             System.out.println("fcp = " + fcp);
  98             for (final AudioFormat from : formats) {
  99                 final AudioInputStream ais = getStream(from);
 100                 for (final AudioFormat to : formats) {
 101                     testAfterConversion(fcp, ais, to);
 102                 }
 103             }
 104         }
 105 
 106         for (final AudioFileWriter afw : load(AudioFileWriter.class)) {
 107             System.out.println("afw = " + afw);
 108             for (final AudioFileFormat.Type type : types) {
 109                 for (final AudioFormat from : formats) {
 110                     testAfterSaveToFile(afw, type, from);
 111                 }
 112             }
 113         }
 114     }
 115 
 116     /**
 117      * Verifies the frame length after the stream was saved/read to/from
 118      * stream.
 119      */
 120     private static void testAfterSaveToFile(AudioFileWriter afw,
 121                                             AudioFileFormat.Type type,
 122                                             AudioFormat from) {
 123         final AudioInputStream ais = getStream(from);
 124         try {
 125             ByteArrayOutputStream out = new ByteArrayOutputStream();
 126             afw.write(ais, type, out);
 127             InputStream input = new ByteArrayInputStream(out.toByteArray());
 128             validate(AudioSystem.getAudioInputStream(input).getFrameLength());
 129         } catch (IllegalArgumentException | UnsupportedAudioFileException
 130                 | IOException ignored) {
 131         }
 132     }
 133 
 134     /**
 135      * Verifies the frame length after the stream was converted to other
 136      * stream.
 137      *
 138      * @see FormatConversionProvider#getAudioInputStream(AudioFormat,
 139      * AudioInputStream)
 140      */
 141     private static void testAfterConversion(FormatConversionProvider fcp,
 142                                             AudioInputStream ais,
 143                                             AudioFormat to) {
 144         if (fcp.isConversionSupported(to, ais.getFormat())) {
 145             validate(fcp.getAudioInputStream(to, ais).getFrameLength());
 146         }
 147     }
 148 
 149     /**
 150      * Throws an exception if the frameLength is specified and is not equal to
 151      * the gold value.
 152      */
 153     private static void validate(final long frameLength) {
 154         if (frameLength != NOT_SPECIFIED && frameLength != FRAME_LENGTH) {
 155             System.err.println("Expected: " + FRAME_LENGTH);
 156             System.err.println("Actual: " + frameLength);
 157             throw new RuntimeException();
 158         }
 159     }
 160 
 161     private static AudioInputStream getStream(final AudioFormat format) {
 162         final InputStream in = new ByteArrayInputStream(new byte[2048]);
 163         return new AudioInputStream(in, format, FRAME_LENGTH);
 164     }
 165 }