|
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 java.io.IOException; |
|
25 import java.io.InputStream; |
|
26 |
|
27 import javax.sound.sampled.AudioFormat; |
|
28 import javax.sound.sampled.AudioInputStream; |
|
29 import javax.sound.sampled.AudioSystem; |
|
30 |
|
31 /** |
|
32 * @test |
|
33 * @bug 4948663 |
|
34 * @summary AudioInputStream does not use the original stream passed to its constructor |
|
35 */ |
|
36 public class AISReadFraction { |
|
37 |
|
38 static int failed = 0; |
|
39 static byte[] testData = new byte[256]; |
|
40 static boolean DEBUG = false; |
|
41 |
|
42 static AudioFormat[] formats = { |
|
43 new AudioFormat(44100.0f, 8, 1, false, false), // frameSize = 1 |
|
44 new AudioFormat(44100.0f, 8, 2, false, false), // frameSize = 2 |
|
45 new AudioFormat(44100.0f, 16, 1, true, false), // frameSize = 2 |
|
46 new AudioFormat(44100.0f, 24, 1, true, false), // frameSize = 3 |
|
47 new AudioFormat(44100.0f, 16, 2, true, false), // frameSize = 4 |
|
48 new AudioFormat(44100.0f, 8, 5, false, false), // frameSize = 5 |
|
49 new AudioFormat(44100.0f, 16, 3, true, false), // frameSize = 6 |
|
50 new AudioFormat(44100.0f, 8, 7, false, false), // frameSize = 7 |
|
51 new AudioFormat(44100.0f, 32, 2, true, false) // frameSize = 8 |
|
52 }; |
|
53 |
|
54 |
|
55 public static void main(String args[]) throws Exception { |
|
56 for (int i = 0; i<testData.length; i++) { |
|
57 testData[i] = (byte) (i % 128); |
|
58 } |
|
59 |
|
60 for (int f = 0; f < formats.length; f++) { |
|
61 // first test without marking |
|
62 doTest(formats[f], false); |
|
63 // then with marking |
|
64 doTest(formats[f], true); |
|
65 } |
|
66 |
|
67 out(""+failed+" failures."); |
|
68 if (failed>0) throw new Exception("Test FAILED!"); |
|
69 out("Test passed."); |
|
70 } |
|
71 |
|
72 static void doTest(AudioFormat format, boolean doMark) { |
|
73 out("Test with"+(doMark?"":"out")+" marking. Audio format: " |
|
74 +"sampleSize="+format.getSampleSizeInBits()+"bits " |
|
75 +"channels="+format.getChannels()+" " |
|
76 +"frameSize="+format.getFrameSize()+"byte(s)"); |
|
77 int maxReadBytes = (testData.length / format.getFrameSize()) * format.getFrameSize(); |
|
78 InputStream is = new FractionalIS(testData, doMark); |
|
79 AudioInputStream ais = new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED); |
|
80 // first some general tests |
|
81 if (ais.markSupported() && !doMark) { |
|
82 out(" #AIS reports markSupported, but underlying stream cannot! FAILED"); |
|
83 failed ++; |
|
84 } |
|
85 if (!ais.markSupported() && doMark) { |
|
86 out(" #AIS does not report markSupported, but underlying stream can mark! FAILED"); |
|
87 failed++; |
|
88 } |
|
89 byte[] data = new byte[1000]; |
|
90 int frameSize = format.getFrameSize(); |
|
91 int counter = 5; |
|
92 int totalReadBytes = 0; |
|
93 boolean hasRead0 = false; |
|
94 boolean hasMarked = false; |
|
95 boolean hasReset = false; |
|
96 int markPos = 0; |
|
97 while (true) { |
|
98 try { |
|
99 int toBeRead = frameSize * counter; |
|
100 counter += 3; |
|
101 if (counter > 14) { |
|
102 counter -= 14; |
|
103 } |
|
104 int read = ais.read(data, 0, toBeRead); |
|
105 if (DEBUG) out(" -> ais.read(data, 0, "+toBeRead+"): "+read+" (frameSize="+frameSize+")"); |
|
106 if ((totalReadBytes == maxReadBytes) && (read != -1) |
|
107 && ((read > 0) || hasRead0)) { |
|
108 if (read == 0) { |
|
109 out(" #stream was read to the end ("+maxReadBytes+"), but ais.read returned repeatedly 0 bytes. FAILED"); |
|
110 } else { |
|
111 out(" #stream was read to the end ("+maxReadBytes+"), but ais.read returned "+read+" bytes... FAILED"); |
|
112 } |
|
113 failed++; |
|
114 break; |
|
115 } |
|
116 if (read > 0) { |
|
117 verifyReadBytes(data, totalReadBytes, read); |
|
118 if ((read % frameSize) != 0) { |
|
119 out(" #Read non-integral number of frames: "+read+" bytes, frameSize="+frameSize+" bytes. FAILED"); |
|
120 failed++; |
|
121 } |
|
122 totalReadBytes += read; |
|
123 hasRead0 = false; |
|
124 } |
|
125 else if (read == 0) { |
|
126 //out(" wanted to read "+toBeRead+" at position "+totalReadBytes+", but got 0 bytes!"); |
|
127 if (hasRead0) { |
|
128 out(" read 0 twice in a row! FAILED"); |
|
129 failed++; |
|
130 break; |
|
131 } |
|
132 hasRead0 = true; |
|
133 } else { |
|
134 // end of stream |
|
135 out(" End of stream reached. Total read bytes: "+totalReadBytes); |
|
136 if (totalReadBytes != maxReadBytes) { |
|
137 out(" #Failed: should have read "+maxReadBytes+" bytes! FAILED."); |
|
138 failed++; |
|
139 } |
|
140 break; |
|
141 } |
|
142 |
|
143 // test marking |
|
144 if (totalReadBytes > 50 && !hasMarked && !hasReset && doMark) { |
|
145 out(" Marking at position "+totalReadBytes); |
|
146 hasMarked = true; |
|
147 ais.mark(0); |
|
148 markPos = totalReadBytes; |
|
149 } |
|
150 if (totalReadBytes > 100 && hasMarked && !hasReset && doMark) { |
|
151 out(" Resetting at position "+totalReadBytes+" back to "+markPos); |
|
152 hasReset = true; |
|
153 ais.reset(); |
|
154 totalReadBytes = markPos; |
|
155 } |
|
156 |
|
157 } catch (IOException e) { |
|
158 out(" #caught unexpected exception:"); |
|
159 e.printStackTrace(); |
|
160 failed++; |
|
161 } |
|
162 } |
|
163 } |
|
164 |
|
165 static void verifyReadBytes(byte[] data, int offset, int len) { |
|
166 int firstWrongByte = -1; |
|
167 for (int i = 0; i < len; i++) { |
|
168 int expected = ((offset + i) % 128); |
|
169 if (data[i] != expected) { |
|
170 out(" read data is not correct! offset="+offset+" expected="+expected+" actual="+data[i]); |
|
171 failed++; |
|
172 break; |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 |
|
178 public static void out(String s) { |
|
179 System.out.println(s); |
|
180 } |
|
181 |
|
182 |
|
183 static class FractionalIS extends InputStream { |
|
184 byte[] data; |
|
185 int pos = 0; |
|
186 boolean canMark; |
|
187 // a counter how many bytes are not returned |
|
188 int missingBytes = 0; |
|
189 int markPos = -1; |
|
190 |
|
191 FractionalIS(byte[] data, boolean canMark) { |
|
192 this.data = data; |
|
193 this.canMark = canMark; |
|
194 } |
|
195 |
|
196 public int read() throws IOException { |
|
197 if (pos >= data.length) { |
|
198 return -1; |
|
199 } |
|
200 return data[pos++] & 0xFF; |
|
201 } |
|
202 |
|
203 public int read(byte[] b, int off, int len) throws IOException { |
|
204 if (++missingBytes > 5) { |
|
205 missingBytes = 0; |
|
206 } |
|
207 int reducedLen = len - missingBytes; |
|
208 if (reducedLen <= 0) reducedLen = 1; |
|
209 if (DEBUG) out(" FIS.read(data, 0, "+len+"): reducing len to "+reducedLen+" bytes."); |
|
210 int ret = super.read(b, off, reducedLen); |
|
211 if (DEBUG) out(" returning "+ret+" bytes. Now at pos="+pos); |
|
212 return ret; |
|
213 } |
|
214 |
|
215 public void mark(int readlimit) { |
|
216 markPos = pos; |
|
217 if (DEBUG) out(" FIS.mark(): marking at "+pos); |
|
218 } |
|
219 |
|
220 public void reset() throws IOException { |
|
221 if (!canMark) { |
|
222 throw new IOException("reset not supported!"); |
|
223 } |
|
224 if (markPos == -1) { |
|
225 throw new IOException("Mark position not set!"); |
|
226 } |
|
227 pos = markPos; |
|
228 if (DEBUG) out(" FIS.reset(): now back at "+pos); |
|
229 } |
|
230 |
|
231 public boolean markSupported() { |
|
232 return canMark; |
|
233 } |
|
234 |
|
235 } |
|
236 |
|
237 } |