16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.media.sound;
27
28 import java.io.IOException;
29 import java.util.Objects;
30 import java.util.Vector;
31
32 import javax.sound.sampled.AudioFormat;
33 import javax.sound.sampled.AudioInputStream;
34 import javax.sound.sampled.AudioSystem;
35
36
37 /**
38 * A-law encodes linear data, and decodes a-law data to linear data.
39 *
40 * @author Kara Kytle
41 */
42 public final class AlawCodec extends SunCodec {
43
44 /* Tables used for A-law decoding */
45
46 private static final byte[] ALAW_TABH = new byte[256];
47 private static final byte[] ALAW_TABL = new byte[256];
48
49 private static final AudioFormat.Encoding[] alawEncodings = { AudioFormat.Encoding.ALAW, AudioFormat.Encoding.PCM_SIGNED };
50
51 private static final short seg_end [] = {0xFF, 0x1FF, 0x3FF,
52 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
53
54 /**
55 * Initializes the decode tables
56 */
57 static {
58 for (int i=0;i<256;i++) {
59 int input = i ^ 0x55;
60 int mantissa = (input & 0xf ) << 4;
61 int segment = (input & 0x70) >> 4;
62 int value = mantissa+8;
63
64 if(segment>=1)
65 value+=0x100;
66 if(segment>1)
67 value <<= (segment -1);
68
69 if( (input & 0x80)==0 )
70 value = -value;
71
72 ALAW_TABL[i] = (byte)value;
73 ALAW_TABH[i] = (byte)(value>>8);
74 }
75 }
76
77
78 /**
79 * Constructs a new ALAW codec object.
80 */
81 public AlawCodec() {
82
83 super(alawEncodings, alawEncodings);
84 }
85
86 // NEW CODE
87
88 /**
89 */
90 public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat){
91
92 if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED )) {
93
94 if( sourceFormat.getSampleSizeInBits() == 16 ) {
95
96 AudioFormat.Encoding enc[] = new AudioFormat.Encoding[1];
97 enc[0] = AudioFormat.Encoding.ALAW;
98 return enc;
99
100 } else {
101 return new AudioFormat.Encoding[0];
102 }
103 } else if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.ALAW ) ) {
104
105 if( sourceFormat.getSampleSizeInBits() == 8 ) {
106
107 AudioFormat.Encoding enc[] = new AudioFormat.Encoding[1];
108 enc[0] = AudioFormat.Encoding.PCM_SIGNED;
109 return enc;
110
111 } else {
112 return new AudioFormat.Encoding[0];
113 }
114
115 } else {
116 return new AudioFormat.Encoding[0];
117 }
118 }
119
120 /**
121 */
122 public AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat){
123 Objects.requireNonNull(sourceFormat);
124 if( (targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) && sourceFormat.getEncoding().equals( AudioFormat.Encoding.ALAW)) ||
125 (targetEncoding.equals( AudioFormat.Encoding.ALAW) && sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED)) ) {
126 return getOutputFormats( sourceFormat );
127 } else {
128 return new AudioFormat[0];
129 }
130 }
131
132 /**
133 */
134 public AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream){
135 AudioFormat sourceFormat = sourceStream.getFormat();
136 AudioFormat.Encoding sourceEncoding = sourceFormat.getEncoding();
137
138 if( !isConversionSupported(targetEncoding,sourceStream.getFormat()) ) {
139 throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString());
140 }
141 if( sourceEncoding.equals( targetEncoding ) ) {
142 return sourceStream;
143 }
144 AudioFormat targetFormat = null;
145 if( sourceEncoding.equals( AudioFormat.Encoding.ALAW ) &&
146 targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) ) {
147
148 targetFormat = new AudioFormat( targetEncoding,
149 sourceFormat.getSampleRate(),
150 16,
151 sourceFormat.getChannels(),
152 2*sourceFormat.getChannels(),
153 sourceFormat.getSampleRate(),
154 sourceFormat.isBigEndian());
155
156 } else if( sourceEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) &&
157 targetEncoding.equals( AudioFormat.Encoding.ALAW ) ) {
158
159 targetFormat = new AudioFormat( targetEncoding,
160 sourceFormat.getSampleRate(),
161 8,
162 sourceFormat.getChannels(),
163 sourceFormat.getChannels(),
164 sourceFormat.getSampleRate(),
165 false);
166 } else {
167 throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString());
168 }
169 return getConvertedStream(targetFormat, sourceStream);
170 }
171
172 /**
173 * use old code...
174 */
175 public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream){
176 if (!isConversionSupported(targetFormat, sourceStream.getFormat()))
177 throw new IllegalArgumentException("Unsupported conversion: "
178 + sourceStream.getFormat().toString() + " to "
179 + targetFormat.toString());
180 return getConvertedStream( targetFormat, sourceStream );
181 }
182
183
184 // OLD CODE
185
186
187 /**
188 * Opens the codec with the specified parameters.
189 * @param stream stream from which data to be processed should be read
190 * @param outputFormat desired data format of the stream after processing
191 * @return stream from which processed data may be read
192 * @throws IllegalArgumentException if the format combination supplied is
193 * not supported.
194 */
195 /* public AudioInputStream getConvertedStream(AudioFormat outputFormat, AudioInputStream stream) { */
196 private AudioInputStream getConvertedStream(AudioFormat outputFormat, AudioInputStream stream) {
197
198 AudioInputStream cs = null;
199 AudioFormat inputFormat = stream.getFormat();
200
201 if( inputFormat.matches(outputFormat) ) {
202 cs = stream;
203 } else {
204 cs = (AudioInputStream) (new AlawCodecStream(stream, outputFormat));
205 }
206
207 return cs;
208 }
209
210 /**
211 * Obtains the set of output formats supported by the codec
212 * given a particular input format.
213 * If no output formats are supported for this input format,
214 * returns an array of length 0.
215 * @return array of supported output formats.
216 */
217 /* public AudioFormat[] getOutputFormats(AudioFormat inputFormat) { */
218 private AudioFormat[] getOutputFormats(AudioFormat inputFormat) {
219
220
221 Vector<AudioFormat> formats = new Vector<>();
222 AudioFormat format;
223
224 if (inputFormat.getSampleSizeInBits() == 16
225 && AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding())) {
226 format = new AudioFormat(AudioFormat.Encoding.ALAW,
227 inputFormat.getSampleRate(), 8,
228 inputFormat.getChannels(),
229 inputFormat.getChannels(),
230 inputFormat.getSampleRate(), false);
231 formats.addElement(format);
232 }
233 if (inputFormat.getSampleSizeInBits() == 8
234 && AudioFormat.Encoding.ALAW.equals(inputFormat.getEncoding())) {
235 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
236 inputFormat.getSampleRate(), 16,
237 inputFormat.getChannels(),
326 frameSize=1;
327 }
328 }
329
330
331 /*
332 * $$jb 2/23/99
333 * Used to determine segment number in aLaw encoding
334 */
335 private short search(short val, short table[], short size) {
336 for(short i = 0; i < size; i++) {
337 if (val <= table[i]) { return i; }
338 }
339 return size;
340 }
341
342 /**
343 * Note that this won't actually read anything; must read in
344 * two-byte units.
345 */
346 public int read() throws IOException {
347
348 byte[] b = new byte[1];
349 return read(b, 0, b.length);
350 }
351
352
353 public int read(byte[] b) throws IOException {
354
355 return read(b, 0, b.length);
356 }
357
358 public int read(byte[] b, int off, int len) throws IOException {
359
360 // don't read fractional frames
361 if( len%frameSize != 0 ) {
362 len -= (len%frameSize);
363 }
364
365 if (encode) {
366
367 short QUANT_MASK = 0xF;
368 short SEG_SHIFT = 4;
369 short mask;
370 short seg;
371 int adj;
372 int i;
373
374 short sample;
375 byte enc;
376
377 int readCount = 0;
|
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.media.sound;
27
28 import java.io.IOException;
29 import java.util.Objects;
30 import java.util.Vector;
31
32 import javax.sound.sampled.AudioFormat;
33 import javax.sound.sampled.AudioInputStream;
34 import javax.sound.sampled.AudioSystem;
35
36 /**
37 * A-law encodes linear data, and decodes a-law data to linear data.
38 *
39 * @author Kara Kytle
40 */
41 public final class AlawCodec extends SunCodec {
42
43 /* Tables used for A-law decoding */
44
45 private static final byte[] ALAW_TABH = new byte[256];
46 private static final byte[] ALAW_TABL = new byte[256];
47
48 private static final AudioFormat.Encoding[] alawEncodings = { AudioFormat.Encoding.ALAW, AudioFormat.Encoding.PCM_SIGNED };
49
50 private static final short seg_end [] = {0xFF, 0x1FF, 0x3FF,
51 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
52
53 /**
54 * Initializes the decode tables.
55 */
56 static {
57 for (int i=0;i<256;i++) {
58 int input = i ^ 0x55;
59 int mantissa = (input & 0xf ) << 4;
60 int segment = (input & 0x70) >> 4;
61 int value = mantissa+8;
62
63 if(segment>=1)
64 value+=0x100;
65 if(segment>1)
66 value <<= (segment -1);
67
68 if( (input & 0x80)==0 )
69 value = -value;
70
71 ALAW_TABL[i] = (byte)value;
72 ALAW_TABH[i] = (byte)(value>>8);
73 }
74 }
75
76
77 /**
78 * Constructs a new ALAW codec object.
79 */
80 public AlawCodec() {
81
82 super(alawEncodings, alawEncodings);
83 }
84
85 @Override
86 public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat){
87
88 if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED )) {
89
90 if( sourceFormat.getSampleSizeInBits() == 16 ) {
91
92 AudioFormat.Encoding enc[] = new AudioFormat.Encoding[1];
93 enc[0] = AudioFormat.Encoding.ALAW;
94 return enc;
95
96 } else {
97 return new AudioFormat.Encoding[0];
98 }
99 } else if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.ALAW ) ) {
100
101 if( sourceFormat.getSampleSizeInBits() == 8 ) {
102
103 AudioFormat.Encoding enc[] = new AudioFormat.Encoding[1];
104 enc[0] = AudioFormat.Encoding.PCM_SIGNED;
105 return enc;
106
107 } else {
108 return new AudioFormat.Encoding[0];
109 }
110
111 } else {
112 return new AudioFormat.Encoding[0];
113 }
114 }
115
116 @Override
117 public AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat){
118 Objects.requireNonNull(sourceFormat);
119 if( (targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) && sourceFormat.getEncoding().equals( AudioFormat.Encoding.ALAW)) ||
120 (targetEncoding.equals( AudioFormat.Encoding.ALAW) && sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED)) ) {
121 return getOutputFormats( sourceFormat );
122 } else {
123 return new AudioFormat[0];
124 }
125 }
126
127 @Override
128 public AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream){
129 AudioFormat sourceFormat = sourceStream.getFormat();
130 AudioFormat.Encoding sourceEncoding = sourceFormat.getEncoding();
131
132 if( !isConversionSupported(targetEncoding,sourceStream.getFormat()) ) {
133 throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString());
134 }
135 if( sourceEncoding.equals( targetEncoding ) ) {
136 return sourceStream;
137 }
138 AudioFormat targetFormat = null;
139 if( sourceEncoding.equals( AudioFormat.Encoding.ALAW ) &&
140 targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) ) {
141
142 targetFormat = new AudioFormat( targetEncoding,
143 sourceFormat.getSampleRate(),
144 16,
145 sourceFormat.getChannels(),
146 2*sourceFormat.getChannels(),
147 sourceFormat.getSampleRate(),
148 sourceFormat.isBigEndian());
149
150 } else if( sourceEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) &&
151 targetEncoding.equals( AudioFormat.Encoding.ALAW ) ) {
152
153 targetFormat = new AudioFormat( targetEncoding,
154 sourceFormat.getSampleRate(),
155 8,
156 sourceFormat.getChannels(),
157 sourceFormat.getChannels(),
158 sourceFormat.getSampleRate(),
159 false);
160 } else {
161 throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString());
162 }
163 return getConvertedStream(targetFormat, sourceStream);
164 }
165
166 @Override
167 public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream){
168 if (!isConversionSupported(targetFormat, sourceStream.getFormat()))
169 throw new IllegalArgumentException("Unsupported conversion: "
170 + sourceStream.getFormat().toString() + " to "
171 + targetFormat.toString());
172 return getConvertedStream( targetFormat, sourceStream );
173 }
174
175 /**
176 * Opens the codec with the specified parameters.
177 * @param stream stream from which data to be processed should be read
178 * @param outputFormat desired data format of the stream after processing
179 * @return stream from which processed data may be read
180 * @throws IllegalArgumentException if the format combination supplied is
181 * not supported.
182 */
183 private AudioInputStream getConvertedStream(AudioFormat outputFormat, AudioInputStream stream) {
184
185 AudioInputStream cs = null;
186 AudioFormat inputFormat = stream.getFormat();
187
188 if( inputFormat.matches(outputFormat) ) {
189 cs = stream;
190 } else {
191 cs = new AlawCodecStream(stream, outputFormat);
192 }
193
194 return cs;
195 }
196
197 /**
198 * Obtains the set of output formats supported by the codec
199 * given a particular input format.
200 * If no output formats are supported for this input format,
201 * returns an array of length 0.
202 * @return array of supported output formats.
203 */
204 private AudioFormat[] getOutputFormats(AudioFormat inputFormat) {
205
206
207 Vector<AudioFormat> formats = new Vector<>();
208 AudioFormat format;
209
210 if (inputFormat.getSampleSizeInBits() == 16
211 && AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding())) {
212 format = new AudioFormat(AudioFormat.Encoding.ALAW,
213 inputFormat.getSampleRate(), 8,
214 inputFormat.getChannels(),
215 inputFormat.getChannels(),
216 inputFormat.getSampleRate(), false);
217 formats.addElement(format);
218 }
219 if (inputFormat.getSampleSizeInBits() == 8
220 && AudioFormat.Encoding.ALAW.equals(inputFormat.getEncoding())) {
221 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
222 inputFormat.getSampleRate(), 16,
223 inputFormat.getChannels(),
312 frameSize=1;
313 }
314 }
315
316
317 /*
318 * $$jb 2/23/99
319 * Used to determine segment number in aLaw encoding
320 */
321 private short search(short val, short table[], short size) {
322 for(short i = 0; i < size; i++) {
323 if (val <= table[i]) { return i; }
324 }
325 return size;
326 }
327
328 /**
329 * Note that this won't actually read anything; must read in
330 * two-byte units.
331 */
332 @Override
333 public int read() throws IOException {
334
335 byte[] b = new byte[1];
336 return read(b, 0, b.length);
337 }
338
339 @Override
340 public int read(byte[] b) throws IOException {
341
342 return read(b, 0, b.length);
343 }
344
345 @Override
346 public int read(byte[] b, int off, int len) throws IOException {
347
348 // don't read fractional frames
349 if( len%frameSize != 0 ) {
350 len -= (len%frameSize);
351 }
352
353 if (encode) {
354
355 short QUANT_MASK = 0xF;
356 short SEG_SHIFT = 4;
357 short mask;
358 short seg;
359 int adj;
360 int i;
361
362 short sample;
363 byte enc;
364
365 int readCount = 0;
|