Path: blob/master/test/jdk/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFiles.java
40527 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.ByteArrayInputStream;2425import javax.sound.sampled.AudioFileFormat;26import javax.sound.sampled.AudioFormat;27import javax.sound.sampled.AudioInputStream;28import javax.sound.sampled.AudioSystem;2930/**31* @test32* @bug 8132782 672983633*/34public final class RecognizeHugeWaveFiles {3536/**37* The maximum size in bytes per WAVE specification.38*/39private static final /*unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL;4041/**42* The supported wave pcm_float format and sample size in bits.43*/44private static final byte[][] waveTypeBits = {45{0x0001/*WAVE_FORMAT_PCM*/,1},46{0x0001/*WAVE_FORMAT_PCM*/,2},47{0x0001/*WAVE_FORMAT_PCM*/,4},48{0x0001/*WAVE_FORMAT_PCM*/,8},49{0x0001/*WAVE_FORMAT_PCM*/,16},50{0x0001/*WAVE_FORMAT_PCM*/,20},51{0x0001/*WAVE_FORMAT_PCM*/,24},52{0x0001/*WAVE_FORMAT_PCM*/,32},53{0x0003/*WAVE_FORMAT_IEEE_FLOAT*/, 32},54{0x0006/*WAVE_FORMAT_ALAW*/, 8},55{0x0007/*WAVE_FORMAT_MULAW*/, 8}56};5758/**59* The list of supported sample rates(stored as unsigned int).60*/61private static final int[] sampleRates = {628000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000,6350000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400,645644800, Integer.MAX_VALUE65};6667/**68* The list of supported channels (stored as unsigned int).69*/70private static final int[] channels = {711, 2, 3, 4, 5, 6, 7, 8, 9, 1072};7374/**75* The list of supported size of data (stored as unsigned int).76* <p>77* The {@code MAX_UNSIGNED_INT} is a maximum size.78*/79private static final long[] dataSizes = {800, 1, 2, 3, Integer.MAX_VALUE - 1, Integer.MAX_VALUE,81(long) Integer.MAX_VALUE + 1, MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT82};8384public static void main(final String[] args) throws Exception {85for (final byte[] type : waveTypeBits) {86for (final int sampleRate : sampleRates) {87for (final int channel : channels) {88for (final long dataSize : dataSizes) {89testAFF(type, sampleRate, channel, dataSize);90testAIS(type, sampleRate, channel, dataSize);91}92}93}94}95}9697/**98* Tests the {@code AudioFileFormat} fetched from the fake header.99* <p>100* Note that the frameLength and byteLength are stored as int which means101* that {@code AudioFileFormat} will store the data above {@code MAX_INT} as102* NOT_SPECIFIED.103*/104private static void testAFF(final byte[] type, final int rate,105final int channel, final long size)106throws Exception {107final byte[] header = createHeader(type, rate, channel, size);108final ByteArrayInputStream fake = new ByteArrayInputStream(header);109final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake);110final AudioFormat format = aff.getFormat();111112if (aff.getType() != AudioFileFormat.Type.WAVE) {113throw new RuntimeException("Error");114}115116final long frameLength = size / format.getFrameSize();117if (frameLength <= Integer.MAX_VALUE) {118if (aff.getFrameLength() != frameLength) {119System.err.println("Expected: " + frameLength);120System.err.println("Actual: " + aff.getFrameLength());121throw new RuntimeException();122}123} else {124if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) {125System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);126System.err.println("Actual: " + aff.getFrameLength());127throw new RuntimeException();128}129}130validateFormat(type[1], rate, channel, aff.getFormat());131}132133/**134* Tests the {@code AudioInputStream} fetched from the fake header.135* <p>136* Note that the frameLength is stored as long which means that {@code137* AudioInputStream} must store all possible data from wave file.138*/139private static void testAIS(final byte[] type, final int rate,140final int channel, final long size)141throws Exception {142final byte[] header = createHeader(type, rate, channel, size);143final ByteArrayInputStream fake = new ByteArrayInputStream(header);144final AudioInputStream ais = AudioSystem.getAudioInputStream(fake);145final AudioFormat format = ais.getFormat();146final long frameLength = size / format.getFrameSize();147if (frameLength != ais.getFrameLength()) {148System.err.println("Expected: " + frameLength);149System.err.println("Actual: " + ais.getFrameLength());150throw new RuntimeException();151}152if (ais.available() < 0) {153System.err.println("available should be >=0: " + ais.available());154throw new RuntimeException();155}156157validateFormat(type[1], rate, channel, format);158}159160/**161* Tests that format contains the same data as were provided to the fake162* stream.163*/164private static void validateFormat(final byte bits, final int rate,165final int channel,166final AudioFormat format) {167168if (Float.compare(format.getSampleRate(), rate) != 0) {169System.err.println("Expected: " + rate);170System.err.println("Actual: " + format.getSampleRate());171throw new RuntimeException();172}173if (format.getChannels() != channel) {174System.err.println("Expected: " + channel);175System.err.println("Actual: " + format.getChannels());176throw new RuntimeException();177}178int frameSize = ((bits + 7) / 8) * channel;179if (format.getFrameSize() != frameSize) {180System.err.println("Expected: " + frameSize);181System.err.println("Actual: " + format.getFrameSize());182throw new RuntimeException();183}184}185186/**187* Creates the custom header of the WAVE file. It is expected that all188* passed data are supported.189*/190private static byte[] createHeader(final byte[] type, final int rate,191final int channel, final long size) {192final int frameSize = ((type[1] + 7) / 8) * channel;193return new byte[]{194// RIFF_MAGIC1950x52, 0x49, 0x46, 0x46,196// fileLength197-1, -1, -1, -1,198// waveMagic1990x57, 0x41, 0x56, 0x45,200// FMT_MAGIC2010x66, 0x6d, 0x74, 0x20,202// size20316, 0, 0, 0,204// wav_type WAVE_FORMAT_IEEE_FLOAT205type[0], 0,206// channels207(byte) (channel), (byte) (channel >> 8),208// samplerate209(byte) (rate), (byte) (rate >> 8), (byte) (rate >> 16),210(byte) (rate >> 24),211// framerate2121, 0, 0, 0,213// framesize214(byte) (frameSize), (byte) (frameSize >> 8),215// bits216type[1], 0,217// DATA_MAGIC2180x64, 0x61, 0x74, 0x61,219// data size220(byte) (size), (byte) (size >> 8), (byte) (size >> 16),221(byte) (size >> 24)222// data223, 0, 0, 0, 0, 0224};225}226}227228229