1/*
2 * Copyright (c) 2002, 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.InputStream;
27import java.io.OutputStream;
28
29import javax.sound.sampled.AudioFormat;
30import javax.sound.sampled.AudioInputStream;
31import javax.sound.sampled.AudioSystem;
32
33/**
34 * @test
35 * @bug 4714846
36 * @summary JavaSound ULAW (8-bit) encoder erroneously depends on endian-ness
37 */
38public class AlawUlaw {
39    static ByteArrayInputStream in;
40    static int byteLength = 1000;
41
42    static boolean failed = false;
43
44    public static void main(String[] args) throws Exception {
45        // generate some random data
46        byte[] soundData = new byte[byteLength];
47        for (int i=0; i<soundData.length; i++) {
48            soundData[i] = (byte) ((i % 256) - 128);
49        }
50
51        // create an AudioInputStream from it
52        in = new ByteArrayInputStream(soundData);
53        in.mark(1);
54
55        test1(PCM_FORMAT_1, ULAW_FORMAT_1, ULAW_FORMAT_2);
56        test1(PCM_FORMAT_2, ULAW_FORMAT_1, ULAW_FORMAT_2);
57        test2(ULAW_FORMAT_1, ULAW_FORMAT_2, PCM_FORMAT_1);
58        test2(ULAW_FORMAT_1, ULAW_FORMAT_2, PCM_FORMAT_2);
59
60        test1(PCM_FORMAT_1, ALAW_FORMAT_1, ALAW_FORMAT_2);
61        test1(PCM_FORMAT_2, ALAW_FORMAT_1, ALAW_FORMAT_2);
62        test2(ALAW_FORMAT_1, ALAW_FORMAT_2, PCM_FORMAT_1);
63        test2(ALAW_FORMAT_1, ALAW_FORMAT_2, PCM_FORMAT_2);
64
65        if (failed) {
66                throw new Exception("Test failed!");
67        }
68    }
69
70    public static String printFormat(AudioFormat format) {
71        return format.toString()+"  "+(format.isBigEndian()?"big":"little")+" endian";
72    }
73
74
75    public static void test1(AudioFormat inFormat, AudioFormat outFormat1, AudioFormat outFormat2) throws Exception {
76        AudioInputStream inStream = new AudioInputStream(in, inFormat, -1);
77        System.out.println("Input Format: " + printFormat(inStream.getFormat()));
78
79        // get a converted stream
80        AudioInputStream stream1 = AudioSystem.getAudioInputStream(outFormat1, inStream);
81        System.out.println("Output Format 1: " + printFormat(stream1.getFormat()));
82
83        // get a converted stream in big endian ulaw
84        AudioInputStream stream2 = AudioSystem.getAudioInputStream(outFormat2, inStream);
85        System.out.println("Output Format 2: " + printFormat(stream2.getFormat()));
86
87        compareStreams(stream1, stream2);
88    }
89
90    public static void test2(AudioFormat inFormat1, AudioFormat inFormat2, AudioFormat outFormat) throws Exception {
91        AudioInputStream inStream1 = new AudioInputStream(in, inFormat1, -1);
92        System.out.println("Input Format1: " + printFormat(inStream1.getFormat()));
93
94        // get a converted stream
95        AudioInputStream stream1 = AudioSystem.getAudioInputStream(outFormat, inStream1);
96        System.out.println("Output Format 1: " + printFormat(stream1.getFormat()));
97
98        AudioInputStream inStream2 = new AudioInputStream(in, inFormat2, -1);
99        System.out.println("Input Format1: " + printFormat(inStream2.getFormat()));
100
101        // get a converted stream in big endian ulaw
102        AudioInputStream stream2 = AudioSystem.getAudioInputStream(outFormat, inStream2);
103        System.out.println("Output Format 2: " + printFormat(stream2.getFormat()));
104
105        compareStreams(stream1, stream2);
106    }
107
108    public static void compareStreams(InputStream stream1, InputStream stream2) throws Exception {
109        ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
110        ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
111
112        in.reset();
113        writeDirectly(stream1, baos1);
114        in.reset();
115        writeDirectly(stream2, baos2);
116
117        if (baos1.size() != baos2.size()) {
118            System.out.println("   stream1 has length = "+baos1.size()+", stream2 has length = "+baos2.size());
119        }
120        int len = baos1.size();
121        if (len > baos2.size()) {
122                len = baos2.size();
123        }
124        byte[] data1=baos1.toByteArray();
125        byte[] data2=baos2.toByteArray();
126        for (int i=0; i<len; i++) {
127                if (data1[i] != data2[i]) {
128                        System.out.println("  FAILED! Difference encountered at position "+i);
129                        failed = true;
130                        return;
131                }
132        }
133        if (baos1.size() != baos2.size()) {
134                System.out.println("  No difference, but different length!");
135                failed = true;
136                return;
137        }
138        System.out.println("   PASSED");
139    }
140
141    public static void writeDirectly(InputStream in, OutputStream out) throws Exception {
142            // read data from the stream until we reach the end of the stream
143            byte tmp[] = new byte[16384];
144            while (true) {
145                int bytesRead = in.read(tmp, 0, tmp.length);
146                if (bytesRead == -1) {
147                        break;
148                }
149                out.write(tmp, 0, bytesRead);
150            } // while
151    }
152
153    public static final AudioFormat PCM_FORMAT_1 =
154        new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
155                         8000f, //sample rate
156                         16, //bits per sample
157                         1, //channels
158                         2, //frame size
159                         8000f, // frame rate
160                         false); //isBigEndian
161    public static final AudioFormat PCM_FORMAT_2 =
162        new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
163                         8000f, //sample rate
164                         16, //bits per sample
165                         1, //channels
166                         2, //frame size
167                         8000f, // frame rate
168                         true); //isBigEndian
169
170    public static final AudioFormat ULAW_FORMAT_1 =
171        new AudioFormat( AudioFormat.Encoding.ULAW,
172                         8000f, //sample rate
173                         8, //bits per sample
174                         1, //channels
175                         1, //frame size
176                         8000f, // frame rate
177                         false); //isBigEndian
178
179    public static final AudioFormat ULAW_FORMAT_2 =
180        new AudioFormat( AudioFormat.Encoding.ULAW,
181                         8000f, //sample rate
182                         8, //bits per sample
183                         1, //channels
184                         1, //frame size
185                         8000f, // frame rate
186                         true); //isBigEndian
187
188    public static final AudioFormat ALAW_FORMAT_1 =
189        new AudioFormat( AudioFormat.Encoding.ALAW,
190                         8000f, //sample rate
191                         8, //bits per sample
192                         1, //channels
193                         1, //frame size
194                         8000f, // frame rate
195                         false); //isBigEndian
196
197    public static final AudioFormat ALAW_FORMAT_2 =
198        new AudioFormat( AudioFormat.Encoding.ALAW,
199                         8000f, //sample rate
200                         8, //bits per sample
201                         1, //channels
202                         1, //frame size
203                         8000f, // frame rate
204                         true); //isBigEndian
205}
206