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
24import java.io.ByteArrayInputStream;
25import java.io.ByteArrayOutputStream;
26import java.io.File;
27import java.io.IOException;
28import java.io.InputStream;
29import java.io.OutputStream;
30import java.nio.file.Files;
31import java.nio.file.Paths;
32import java.util.ArrayList;
33import java.util.List;
34
35import javax.sound.sampled.AudioFileFormat;
36import javax.sound.sampled.AudioFileFormat.Type;
37import javax.sound.sampled.AudioFormat;
38import javax.sound.sampled.AudioInputStream;
39import javax.sound.sampled.AudioSystem;
40import javax.sound.sampled.spi.AudioFileWriter;
41
42import static java.util.ServiceLoader.load;
43import static javax.sound.sampled.AudioFileFormat.Type.AIFC;
44import static javax.sound.sampled.AudioFileFormat.Type.AIFF;
45import static javax.sound.sampled.AudioFileFormat.Type.AU;
46import static javax.sound.sampled.AudioFileFormat.Type.SND;
47import static javax.sound.sampled.AudioFileFormat.Type.WAVE;
48
49/**
50 * @test
51 * @bug 8064800
52 */
53public final class WriteUnsupportedAudioFormat {
54
55    /**
56     * We will try to use all formats, in this case all our providers will be
57     * covered by supported/unsupported formats.
58     */
59    private static final List<AudioFormat> formats = new ArrayList<>(23000);
60
61    private static final AudioFormat.Encoding[] encodings = {
62            AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW,
63            AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED,
64            AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test")
65    };
66
67    private static final int[] sampleRates = {
68            /*AudioSystem.NOT_SPECIFIED,*/ 8000, 11025, 16000, 22050, 32000,
69            37800, 44056, 44100, 47250, 48000, 50000, 50400, 88200, 96000,
70            176400, 192000, 352800, 2822400, 5644800
71    };
72
73    private static final int[] sampleBits = {
74            /*AudioSystem.NOT_SPECIFIED, 4,*/ 8,/* 11,*/ 16/*, 20*/, 24,
75            32/*, 48, 64, 128*/
76    };
77
78    public static final int BUFFER_LEN = 127;
79
80    private static final int[] channels = {
81            /*AudioSystem.NOT_SPECIFIED,*/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
82    };
83
84    static final Type[] types = {
85            WAVE, AU, AIFF, AIFC, SND, new Type("TestName", "TestExt")
86    };
87
88    private static final File FILE;
89
90    static {
91        try {
92            FILE = File.createTempFile("sound", null);
93        } catch (final IOException e) {
94            throw new RuntimeException(e);
95        }
96
97        for (final Boolean end : new boolean[]{false, true}) {
98            for (final int sampleSize : sampleBits) {
99                for (final int sampleRate : sampleRates) {
100                    for (final int channel : channels) {
101                        for (final AudioFormat.Encoding enc : encodings) {
102
103                            if (enc.equals(AudioFormat.Encoding.PCM_FLOAT)
104                                    && sampleSize != 32) {
105                                continue;
106                            }
107                            if (enc.equals(AudioFormat.Encoding.ALAW)
108                                    && sampleSize != 8) {
109                                continue;
110                            }
111                            if (enc.equals(AudioFormat.Encoding.ULAW)
112                                    && sampleSize != 8) {
113                                continue;
114                            }
115
116                            final int frameSize = ((sampleSize + 7) / 8)
117                                    * channel;
118                            formats.add(
119                                    new AudioFormat(enc, sampleRate, sampleSize,
120                                                    channel, frameSize,
121                                                    sampleRate, end));
122                        }
123                    }
124                }
125            }
126        }
127    }
128
129    public static void main(final String[] args) throws Exception {
130        for (final AudioFileFormat.Type type : types) {
131            for (final AudioFormat format : formats) {
132                testAS(type, format);
133                for (final AudioFileWriter afw : load(AudioFileWriter.class)) {
134                    testAFW(afw, type, format);
135                }
136            }
137        }
138        Files.delete(Paths.get(FILE.getAbsolutePath()));
139    }
140
141    /**
142     * Tests the part of AudioSystem API, which implemented via AudioFileWriter.
143     */
144    private static void testAS(final AudioFileFormat.Type type,
145                               final AudioFormat format) throws Exception {
146        final AudioInputStream ais = getStream(format);
147        final OutputStream buffer = new ByteArrayOutputStream(BUFFER_LEN);
148
149        if (AudioSystem.isFileTypeSupported(type, ais)) {
150            if (!AudioSystem.isFileTypeSupported(type)) {
151                throw new RuntimeException(type + ", " + format);
152            }
153            try {
154                AudioSystem.write(ais, type, buffer);
155                AudioSystem.write(ais, type, FILE);
156            } catch (final IllegalArgumentException e) {
157                throw new RuntimeException(type + ", " + format, e);
158            }
159        } else {
160            try {
161                AudioSystem.write(ais, type, buffer);
162                throw new RuntimeException(type + ", " + format);
163            } catch (final IllegalArgumentException ignored) {
164            }
165            try {
166                AudioSystem.write(ais, type, FILE);
167                throw new RuntimeException(type + ", " + format);
168            } catch (final IllegalArgumentException ignored) {
169            }
170        }
171    }
172
173    /**
174     * Tests the AudioFileWriter API directly.
175     */
176    private static void testAFW(final AudioFileWriter afw,
177                                final AudioFileFormat.Type type,
178                                final AudioFormat format) throws Exception {
179        final AudioInputStream ais = getStream(format);
180        final OutputStream buffer = new ByteArrayOutputStream(BUFFER_LEN);
181
182        if (afw.isFileTypeSupported(type, ais)) {
183            if (!afw.isFileTypeSupported(type)) {
184                throw new RuntimeException(type + "," + format + ',' + afw);
185            }
186            try {
187                afw.write(ais, type, buffer);
188                afw.write(ais, type, FILE);
189            } catch (final IllegalArgumentException e) {
190                throw new RuntimeException(type + "," + format + ',' + afw, e);
191            }
192        } else {
193            try {
194                afw.write(ais, type, buffer);
195                throw new RuntimeException(type + "," + format + ',' + afw);
196            } catch (final IllegalArgumentException ignored) {
197            }
198            try {
199                afw.write(ais, type, FILE);
200                throw new RuntimeException(type + "," + format + ',' + afw);
201            } catch (final IllegalArgumentException ignored) {
202            }
203        }
204    }
205
206    private static AudioInputStream getStream(final AudioFormat format) {
207        final InputStream in = new ByteArrayInputStream(new byte[BUFFER_LEN]);
208        return new AudioInputStream(in, format, 10);
209    }
210}
211