Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/media/sound/AlawCodec.java
38924 views
/*1* Copyright (c) 1999, 2013, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.media.sound;2627import java.io.IOException;28import java.util.Vector;2930import javax.sound.sampled.AudioFormat;31import javax.sound.sampled.AudioInputStream;32import javax.sound.sampled.AudioSystem;333435/**36* A-law encodes linear data, and decodes a-law data to linear data.37*38* @author Kara Kytle39*/40public final class AlawCodec extends SunCodec {4142/* Tables used for A-law decoding */4344private static final byte[] ALAW_TABH = new byte[256];45private static final byte[] ALAW_TABL = new byte[256];4647private static final AudioFormat.Encoding[] alawEncodings = { AudioFormat.Encoding.ALAW, AudioFormat.Encoding.PCM_SIGNED };4849private static final short seg_end [] = {0xFF, 0x1FF, 0x3FF,500x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};5152/**53* Initializes the decode tables54*/55static {56for (int i=0;i<256;i++) {57int input = i ^ 0x55;58int mantissa = (input & 0xf ) << 4;59int segment = (input & 0x70) >> 4;60int value = mantissa+8;6162if(segment>=1)63value+=0x100;64if(segment>1)65value <<= (segment -1);6667if( (input & 0x80)==0 )68value = -value;6970ALAW_TABL[i] = (byte)value;71ALAW_TABH[i] = (byte)(value>>8);72}73}747576/**77* Constructs a new ALAW codec object.78*/79public AlawCodec() {8081super(alawEncodings, alawEncodings);82}8384// NEW CODE8586/**87*/88public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat){8990if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED )) {9192if( sourceFormat.getSampleSizeInBits() == 16 ) {9394AudioFormat.Encoding enc[] = new AudioFormat.Encoding[1];95enc[0] = AudioFormat.Encoding.ALAW;96return enc;9798} else {99return new AudioFormat.Encoding[0];100}101} else if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.ALAW ) ) {102103if( sourceFormat.getSampleSizeInBits() == 8 ) {104105AudioFormat.Encoding enc[] = new AudioFormat.Encoding[1];106enc[0] = AudioFormat.Encoding.PCM_SIGNED;107return enc;108109} else {110return new AudioFormat.Encoding[0];111}112113} else {114return new AudioFormat.Encoding[0];115}116}117118/**119*/120public AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat){121if( (targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) && sourceFormat.getEncoding().equals( AudioFormat.Encoding.ALAW)) ||122(targetEncoding.equals( AudioFormat.Encoding.ALAW) && sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED)) ) {123return getOutputFormats( sourceFormat );124} else {125return new AudioFormat[0];126}127}128129/**130*/131public AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream){132AudioFormat sourceFormat = sourceStream.getFormat();133AudioFormat.Encoding sourceEncoding = sourceFormat.getEncoding();134135if( sourceEncoding.equals( targetEncoding ) ) {136return sourceStream;137} else {138AudioFormat targetFormat = null;139if( !isConversionSupported(targetEncoding,sourceStream.getFormat()) ) {140throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString());141}142if( sourceEncoding.equals( AudioFormat.Encoding.ALAW ) &&143targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) ) {144145targetFormat = new AudioFormat( targetEncoding,146sourceFormat.getSampleRate(),14716,148sourceFormat.getChannels(),1492*sourceFormat.getChannels(),150sourceFormat.getSampleRate(),151sourceFormat.isBigEndian());152153} else if( sourceEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) &&154targetEncoding.equals( AudioFormat.Encoding.ALAW ) ) {155156targetFormat = new AudioFormat( targetEncoding,157sourceFormat.getSampleRate(),1588,159sourceFormat.getChannels(),160sourceFormat.getChannels(),161sourceFormat.getSampleRate(),162false);163} else {164throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString());165}166return getAudioInputStream( targetFormat, sourceStream );167}168}169170/**171* use old code...172*/173public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream){174return getConvertedStream( targetFormat, sourceStream );175}176177178// OLD CODE179180181/**182* Opens the codec with the specified parameters.183* @param stream stream from which data to be processed should be read184* @param outputFormat desired data format of the stream after processing185* @return stream from which processed data may be read186* @throws IllegalArgumentException if the format combination supplied is187* not supported.188*/189/* public AudioInputStream getConvertedStream(AudioFormat outputFormat, AudioInputStream stream) { */190private AudioInputStream getConvertedStream(AudioFormat outputFormat, AudioInputStream stream) {191192AudioInputStream cs = null;193AudioFormat inputFormat = stream.getFormat();194195if( inputFormat.matches(outputFormat) ) {196cs = stream;197} else {198cs = (AudioInputStream) (new AlawCodecStream(stream, outputFormat));199}200201return cs;202}203204/**205* Obtains the set of output formats supported by the codec206* given a particular input format.207* If no output formats are supported for this input format,208* returns an array of length 0.209* @return array of supported output formats.210*/211/* public AudioFormat[] getOutputFormats(AudioFormat inputFormat) { */212private AudioFormat[] getOutputFormats(AudioFormat inputFormat) {213214215Vector formats = new Vector();216AudioFormat format;217218if ( AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding())) {219format = new AudioFormat(AudioFormat.Encoding.ALAW,220inputFormat.getSampleRate(),2218,222inputFormat.getChannels(),223inputFormat.getChannels(),224inputFormat.getSampleRate(),225false );226formats.addElement(format);227}228229if (AudioFormat.Encoding.ALAW.equals(inputFormat.getEncoding())) {230format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,231inputFormat.getSampleRate(),23216,233inputFormat.getChannels(),234inputFormat.getChannels()*2,235inputFormat.getSampleRate(),236false );237formats.addElement(format);238format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,239inputFormat.getSampleRate(),24016,241inputFormat.getChannels(),242inputFormat.getChannels()*2,243inputFormat.getSampleRate(),244true );245formats.addElement(format);246}247248AudioFormat[] formatArray = new AudioFormat[formats.size()];249for (int i = 0; i < formatArray.length; i++) {250formatArray[i] = (AudioFormat)(formats.elementAt(i));251}252return formatArray;253}254255256final class AlawCodecStream extends AudioInputStream {257258// tempBuffer required only for encoding (when encode is true)259private static final int tempBufferSize = 64;260private byte tempBuffer [] = null;261262/**263* True to encode to a-law, false to decode to linear264*/265boolean encode = false;266267AudioFormat encodeFormat;268AudioFormat decodeFormat;269270byte tabByte1[] = null;271byte tabByte2[] = null;272int highByte = 0;273int lowByte = 1;274275AlawCodecStream(AudioInputStream stream, AudioFormat outputFormat) {276277super(stream, outputFormat, -1);278279AudioFormat inputFormat = stream.getFormat();280281// throw an IllegalArgumentException if not ok282if ( ! (isConversionSupported(outputFormat, inputFormat)) ) {283284throw new IllegalArgumentException("Unsupported conversion: " + inputFormat.toString() + " to " + outputFormat.toString());285}286287//$$fb 2002-07-18: fix for 4714846: JavaSound ULAW (8-bit) encoder erroneously depends on endian-ness288boolean PCMIsBigEndian;289290// determine whether we are encoding or decoding291if (AudioFormat.Encoding.ALAW.equals(inputFormat.getEncoding())) {292encode = false;293encodeFormat = inputFormat;294decodeFormat = outputFormat;295PCMIsBigEndian = outputFormat.isBigEndian();296} else {297encode = true;298encodeFormat = outputFormat;299decodeFormat = inputFormat;300PCMIsBigEndian = inputFormat.isBigEndian();301tempBuffer = new byte[tempBufferSize];302}303304if (PCMIsBigEndian) {305tabByte1 = ALAW_TABH;306tabByte2 = ALAW_TABL;307highByte = 0;308lowByte = 1;309} else {310tabByte1 = ALAW_TABL;311tabByte2 = ALAW_TABH;312highByte = 1;313lowByte = 0;314}315316// set the AudioInputStream length in frames if we know it317if (stream instanceof AudioInputStream) {318frameLength = ((AudioInputStream)stream).getFrameLength();319}320321// set framePos to zero322framePos = 0;323frameSize = inputFormat.getFrameSize();324if( frameSize==AudioSystem.NOT_SPECIFIED ) {325frameSize=1;326}327}328329330/*331* $$jb 2/23/99332* Used to determine segment number in aLaw encoding333*/334private short search(short val, short table[], short size) {335for(short i = 0; i < size; i++) {336if (val <= table[i]) { return i; }337}338return size;339}340341/**342* Note that this won't actually read anything; must read in343* two-byte units.344*/345public int read() throws IOException {346347byte[] b = new byte[1];348return (int)read(b, 0, b.length);349}350351352public int read(byte[] b) throws IOException {353354return read(b, 0, b.length);355}356357public int read(byte[] b, int off, int len) throws IOException {358359// don't read fractional frames360if( len%frameSize != 0 ) {361len -= (len%frameSize);362}363364if (encode) {365366short QUANT_MASK = 0xF;367short SEG_SHIFT = 4;368short mask;369short seg;370int adj;371int i;372373short sample;374byte enc;375376int readCount = 0;377int currentPos = off;378int readLeft = len*2;379int readLen = ( (readLeft>tempBufferSize) ? tempBufferSize : readLeft );380381while ((readCount = super.read(tempBuffer,0,readLen))>0) {382383for (i = 0; i < readCount; i+=2) {384385/* Get the sample from the tempBuffer */386sample = (short)(( (tempBuffer[i + highByte]) << 8) & 0xFF00);387sample |= (short)( (tempBuffer[i + lowByte]) & 0xFF);388389if(sample >= 0) {390mask = 0xD5;391} else {392mask = 0x55;393sample = (short)(-sample - 8);394}395/* Convert the scaled magnitude to segment number. */396seg = search(sample, seg_end, (short) 8);397/*398* Combine the sign, segment, quantization bits399*/400if (seg >= 8) { /* out of range, return maximum value. */401enc = (byte) (0x7F ^ mask);402} else {403enc = (byte) (seg << SEG_SHIFT);404if(seg < 2) {405enc |= (byte) ( (sample >> 4) & QUANT_MASK);406} else {407enc |= (byte) ( (sample >> (seg + 3)) & QUANT_MASK );408}409enc ^= mask;410}411/* Now put the encoded sample where it belongs */412b[currentPos] = enc;413currentPos++;414}415/* And update pointers and counters for next iteration */416readLeft -= readCount;417readLen = ( (readLeft>tempBufferSize) ? tempBufferSize : readLeft );418}419420if( currentPos==off && readCount<0 ) { // EOF or error421return readCount;422}423424return (currentPos - off); /* Number of bytes written to new buffer */425426} else {427428int i;429int readLen = len/2;430int readOffset = off + len/2;431int readCount = super.read(b, readOffset, readLen);432433for (i = off; i < (off + (readCount*2)); i+=2) {434b[i] = (byte)tabByte1[b[readOffset] & 0xFF];435b[i+1] = (byte)tabByte2[b[readOffset] & 0xFF];436readOffset++;437}438439if( readCount<0 ) { // EOF or error440return readCount;441}442443return (i - off);444}445}446} // end class AlawCodecStream447} // end class ALAW448449450