1 /*
   2  * Copyright (c) 1999, 2013, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  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.Vector;
  30 
  31 import javax.sound.sampled.AudioFormat;
  32 import javax.sound.sampled.AudioInputStream;
  33 import javax.sound.sampled.AudioSystem;
  34 
  35 
  36 /**
  37  * Converts among signed/unsigned and little/big endianness of sampled.
  38  *
  39  * @author Jan Borgersen
  40  */
  41 public final class PCMtoPCMCodec extends SunCodec {
  42 
  43 
  44     private static final AudioFormat.Encoding[] inputEncodings = {
  45         AudioFormat.Encoding.PCM_SIGNED,
  46         AudioFormat.Encoding.PCM_UNSIGNED,
  47     };
  48 
  49     private static final AudioFormat.Encoding[] outputEncodings = {
  50         AudioFormat.Encoding.PCM_SIGNED,
  51         AudioFormat.Encoding.PCM_UNSIGNED,
  52     };
  53 
  54 
  55 
  56     private static final int tempBufferSize = 64;
  57     private byte tempBuffer [] = null;
  58 
  59     /**
  60      * Constructs a new PCMtoPCM codec object.
  61      */
  62     public PCMtoPCMCodec() {
  63 
  64         super( inputEncodings, outputEncodings);
  65     }
  66 
  67     // NEW CODE
  68 
  69 
  70     /**
  71      */
  72     public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat){
  73 
  74         if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED ) ||
  75             sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_UNSIGNED ) ) {
  76 
  77                 AudioFormat.Encoding encs[] = new AudioFormat.Encoding[2];
  78                 encs[0] = AudioFormat.Encoding.PCM_SIGNED;
  79                 encs[1] = AudioFormat.Encoding.PCM_UNSIGNED;
  80                 return encs;
  81             } else {
  82                 return new AudioFormat.Encoding[0];
  83             }
  84     }
  85 
  86 
  87     /**
  88      */
  89     public AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat){
  90 
  91         // filter out targetEncoding from the old getOutputFormats( sourceFormat ) method
  92 
  93         AudioFormat[] formats = getOutputFormats( sourceFormat );
  94         Vector<AudioFormat> newFormats = new Vector<>();
  95         for(int i=0; i<formats.length; i++ ) {
  96             if( formats[i].getEncoding().equals( targetEncoding ) ) {
  97                 newFormats.addElement( formats[i] );
  98             }
  99         }
 100 
 101         AudioFormat[] formatArray = new AudioFormat[newFormats.size()];
 102 
 103         for (int i = 0; i < formatArray.length; i++) {
 104             formatArray[i] = newFormats.elementAt(i);
 105         }
 106 
 107         return formatArray;
 108     }
 109 
 110 
 111     /**
 112      */
 113     public AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream) {
 114 
 115         if( isConversionSupported(targetEncoding, sourceStream.getFormat()) ) {
 116 
 117             AudioFormat sourceFormat = sourceStream.getFormat();
 118             AudioFormat targetFormat = new AudioFormat( targetEncoding,
 119                                                         sourceFormat.getSampleRate(),
 120                                                         sourceFormat.getSampleSizeInBits(),
 121                                                         sourceFormat.getChannels(),
 122                                                         sourceFormat.getFrameSize(),
 123                                                         sourceFormat.getFrameRate(),
 124                                                         sourceFormat.isBigEndian() );
 125 
 126             return getAudioInputStream( targetFormat, sourceStream );
 127 
 128         } else {
 129             throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString() );
 130         }
 131 
 132     }
 133     /**
 134      * use old code
 135      */
 136     public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream){
 137 
 138         return getConvertedStream( targetFormat, sourceStream );
 139     }
 140 
 141 
 142 
 143 
 144     // OLD CODE
 145 
 146     /**
 147      * Opens the codec with the specified parameters.
 148      * @param stream stream from which data to be processed should be read
 149      * @param outputFormat desired data format of the stream after processing
 150      * @return stream from which processed data may be read
 151      * @throws IllegalArgumentException if the format combination supplied is
 152      * not supported.
 153      */
 154     /*  public AudioInputStream getConvertedStream(AudioFormat outputFormat, AudioInputStream stream) {*/
 155     private AudioInputStream getConvertedStream(AudioFormat outputFormat, AudioInputStream stream) {
 156 
 157         AudioInputStream cs = null;
 158 
 159         AudioFormat inputFormat = stream.getFormat();
 160 
 161         if( inputFormat.matches(outputFormat) ) {
 162 
 163             cs = stream;
 164         } else {
 165 
 166             cs = (AudioInputStream) (new PCMtoPCMCodecStream(stream, outputFormat));
 167             tempBuffer = new byte[tempBufferSize];
 168         }
 169         return cs;
 170     }
 171 
 172 
 173 
 174     /**
 175      * Obtains the set of output formats supported by the codec
 176      * given a particular input format.
 177      * If no output formats are supported for this input format,
 178      * returns an array of length 0.
 179      * @return array of supported output formats.
 180      */
 181     /*  public AudioFormat[] getOutputFormats(AudioFormat inputFormat) { */
 182     private AudioFormat[] getOutputFormats(AudioFormat inputFormat) {
 183 
 184         Vector<AudioFormat> formats = new Vector<>();
 185         AudioFormat format;
 186 
 187         int sampleSize = inputFormat.getSampleSizeInBits();
 188         boolean isBigEndian = inputFormat.isBigEndian();
 189 
 190 
 191         if ( sampleSize==8 ) {
 192             if ( AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding()) ) {
 193 
 194                 format = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED,
 195                                          inputFormat.getSampleRate(),
 196                                          inputFormat.getSampleSizeInBits(),
 197                                          inputFormat.getChannels(),
 198                                          inputFormat.getFrameSize(),
 199                                          inputFormat.getFrameRate(),
 200                                          false );
 201                 formats.addElement(format);
 202             }
 203 
 204             if ( AudioFormat.Encoding.PCM_UNSIGNED.equals(inputFormat.getEncoding()) ) {
 205 
 206                 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
 207                                          inputFormat.getSampleRate(),
 208                                          inputFormat.getSampleSizeInBits(),
 209                                          inputFormat.getChannels(),
 210                                          inputFormat.getFrameSize(),
 211                                          inputFormat.getFrameRate(),
 212                                          false );
 213                 formats.addElement(format);
 214             }
 215 
 216         } else if ( sampleSize==16 ) {
 217 
 218             if ( AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding()) && isBigEndian ) {
 219 
 220                 format = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED,
 221                                          inputFormat.getSampleRate(),
 222                                          inputFormat.getSampleSizeInBits(),
 223                                          inputFormat.getChannels(),
 224                                          inputFormat.getFrameSize(),
 225                                          inputFormat.getFrameRate(),
 226                                          true );
 227                 formats.addElement(format);
 228                 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
 229                                          inputFormat.getSampleRate(),
 230                                          inputFormat.getSampleSizeInBits(),
 231                                          inputFormat.getChannels(),
 232                                          inputFormat.getFrameSize(),
 233                                          inputFormat.getFrameRate(),
 234                                          false );
 235                 formats.addElement(format);
 236                 format = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED,
 237                                          inputFormat.getSampleRate(),
 238                                          inputFormat.getSampleSizeInBits(),
 239                                          inputFormat.getChannels(),
 240                                          inputFormat.getFrameSize(),
 241                                          inputFormat.getFrameRate(),
 242                                          false );
 243                 formats.addElement(format);
 244             }
 245 
 246             if ( AudioFormat.Encoding.PCM_UNSIGNED.equals(inputFormat.getEncoding()) && isBigEndian ) {
 247 
 248                 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
 249                                          inputFormat.getSampleRate(),
 250                                          inputFormat.getSampleSizeInBits(),
 251                                          inputFormat.getChannels(),
 252                                          inputFormat.getFrameSize(),
 253                                          inputFormat.getFrameRate(),
 254                                          true );
 255                 formats.addElement(format);
 256                 format = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED,
 257                                          inputFormat.getSampleRate(),
 258                                          inputFormat.getSampleSizeInBits(),
 259                                          inputFormat.getChannels(),
 260                                          inputFormat.getFrameSize(),
 261                                          inputFormat.getFrameRate(),
 262                                          false );
 263                 formats.addElement(format);
 264                 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
 265                                          inputFormat.getSampleRate(),
 266                                          inputFormat.getSampleSizeInBits(),
 267                                          inputFormat.getChannels(),
 268                                          inputFormat.getFrameSize(),
 269                                          inputFormat.getFrameRate(),
 270                                          false );
 271                 formats.addElement(format);
 272             }
 273 
 274             if ( AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding()) && !isBigEndian ) {
 275 
 276                 format = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED,
 277                                          inputFormat.getSampleRate(),
 278                                          inputFormat.getSampleSizeInBits(),
 279                                          inputFormat.getChannels(),
 280                                          inputFormat.getFrameSize(),
 281                                          inputFormat.getFrameRate(),
 282                                          false );
 283                 formats.addElement(format);
 284                 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
 285                                          inputFormat.getSampleRate(),
 286                                          inputFormat.getSampleSizeInBits(),
 287                                          inputFormat.getChannels(),
 288                                          inputFormat.getFrameSize(),
 289                                          inputFormat.getFrameRate(),
 290                                          true );
 291                 formats.addElement(format);
 292                 format = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED,
 293                                          inputFormat.getSampleRate(),
 294                                          inputFormat.getSampleSizeInBits(),
 295                                          inputFormat.getChannels(),
 296                                          inputFormat.getFrameSize(),
 297                                          inputFormat.getFrameRate(),
 298                                          true );
 299                 formats.addElement(format);
 300             }
 301 
 302             if ( AudioFormat.Encoding.PCM_UNSIGNED.equals(inputFormat.getEncoding()) && !isBigEndian ) {
 303 
 304                 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
 305                                          inputFormat.getSampleRate(),
 306                                          inputFormat.getSampleSizeInBits(),
 307                                          inputFormat.getChannels(),
 308                                          inputFormat.getFrameSize(),
 309                                          inputFormat.getFrameRate(),
 310                                          false );
 311                 formats.addElement(format);
 312                 format = new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED,
 313                                          inputFormat.getSampleRate(),
 314                                          inputFormat.getSampleSizeInBits(),
 315                                          inputFormat.getChannels(),
 316                                          inputFormat.getFrameSize(),
 317                                          inputFormat.getFrameRate(),
 318                                          true );
 319                 formats.addElement(format);
 320                 format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
 321                                          inputFormat.getSampleRate(),
 322                                          inputFormat.getSampleSizeInBits(),
 323                                          inputFormat.getChannels(),
 324                                          inputFormat.getFrameSize(),
 325                                          inputFormat.getFrameRate(),
 326                                          true );
 327                 formats.addElement(format);
 328             }
 329         }
 330         AudioFormat[] formatArray;
 331 
 332         synchronized(formats) {
 333 
 334             formatArray = new AudioFormat[formats.size()];
 335 
 336             for (int i = 0; i < formatArray.length; i++) {
 337 
 338                 formatArray[i] = formats.elementAt(i);
 339             }
 340         }
 341 
 342         return formatArray;
 343     }
 344 
 345 
 346     class PCMtoPCMCodecStream extends AudioInputStream {
 347 
 348         private final int PCM_SWITCH_SIGNED_8BIT                = 1;
 349         private final int PCM_SWITCH_ENDIAN                             = 2;
 350         private final int PCM_SWITCH_SIGNED_LE                  = 3;
 351         private final int PCM_SWITCH_SIGNED_BE                  = 4;
 352         private final int PCM_UNSIGNED_LE2SIGNED_BE             = 5;
 353         private final int PCM_SIGNED_LE2UNSIGNED_BE             = 6;
 354         private final int PCM_UNSIGNED_BE2SIGNED_LE             = 7;
 355         private final int PCM_SIGNED_BE2UNSIGNED_LE             = 8;
 356 
 357         private final int sampleSizeInBytes;
 358         private int conversionType = 0;
 359 
 360 
 361         PCMtoPCMCodecStream(AudioInputStream stream, AudioFormat outputFormat) {
 362 
 363             super(stream, outputFormat, -1);
 364 
 365             int sampleSizeInBits = 0;
 366             AudioFormat.Encoding inputEncoding = null;
 367             AudioFormat.Encoding outputEncoding = null;
 368             boolean inputIsBigEndian;
 369             boolean outputIsBigEndian;
 370 
 371             AudioFormat inputFormat = stream.getFormat();
 372 
 373             // throw an IllegalArgumentException if not ok
 374             if ( ! (isConversionSupported(inputFormat, outputFormat)) ) {
 375 
 376                 throw new IllegalArgumentException("Unsupported conversion: " + inputFormat.toString() + " to " + outputFormat.toString());
 377             }
 378 
 379             inputEncoding = inputFormat.getEncoding();
 380             outputEncoding = outputFormat.getEncoding();
 381             inputIsBigEndian = inputFormat.isBigEndian();
 382             outputIsBigEndian = outputFormat.isBigEndian();
 383             sampleSizeInBits = inputFormat.getSampleSizeInBits();
 384             sampleSizeInBytes = sampleSizeInBits/8;
 385 
 386             // determine conversion to perform
 387 
 388             if( sampleSizeInBits==8 ) {
 389                 if( AudioFormat.Encoding.PCM_UNSIGNED.equals(inputEncoding) &&
 390                     AudioFormat.Encoding.PCM_SIGNED.equals(outputEncoding) ) {
 391                     conversionType = PCM_SWITCH_SIGNED_8BIT;
 392                     if(Printer.debug) Printer.debug("PCMtoPCMCodecStream: conversionType = PCM_SWITCH_SIGNED_8BIT");
 393 
 394                 } else if( AudioFormat.Encoding.PCM_SIGNED.equals(inputEncoding) &&
 395                            AudioFormat.Encoding.PCM_UNSIGNED.equals(outputEncoding) ) {
 396                     conversionType = PCM_SWITCH_SIGNED_8BIT;
 397                     if(Printer.debug) Printer.debug("PCMtoPCMCodecStream: conversionType = PCM_SWITCH_SIGNED_8BIT");
 398                 }
 399             } else {
 400 
 401                 if( inputEncoding.equals(outputEncoding) && (inputIsBigEndian != outputIsBigEndian) ) {
 402 
 403                     conversionType = PCM_SWITCH_ENDIAN;
 404                     if(Printer.debug) Printer.debug("PCMtoPCMCodecStream: conversionType = PCM_SWITCH_ENDIAN");
 405 
 406 
 407                 } else if (AudioFormat.Encoding.PCM_UNSIGNED.equals(inputEncoding) && !inputIsBigEndian &&
 408                             AudioFormat.Encoding.PCM_SIGNED.equals(outputEncoding) && outputIsBigEndian) {
 409 
 410                     conversionType = PCM_UNSIGNED_LE2SIGNED_BE;
 411                     if(Printer.debug) Printer.debug("PCMtoPCMCodecStream: conversionType = PCM_UNSIGNED_LE2SIGNED_BE");
 412 
 413                 } else if (AudioFormat.Encoding.PCM_SIGNED.equals(inputEncoding) && !inputIsBigEndian &&
 414                            AudioFormat.Encoding.PCM_UNSIGNED.equals(outputEncoding) && outputIsBigEndian) {
 415 
 416                     conversionType = PCM_SIGNED_LE2UNSIGNED_BE;
 417                     if(Printer.debug) Printer.debug("PCMtoPCMCodecStream: conversionType = PCM_SIGNED_LE2UNSIGNED_BE");
 418 
 419                 } else if (AudioFormat.Encoding.PCM_UNSIGNED.equals(inputEncoding) && inputIsBigEndian &&
 420                            AudioFormat.Encoding.PCM_SIGNED.equals(outputEncoding) && !outputIsBigEndian) {
 421 
 422                     conversionType = PCM_UNSIGNED_BE2SIGNED_LE;
 423                     if(Printer.debug) Printer.debug("PCMtoPCMCodecStream: conversionType = PCM_UNSIGNED_BE2SIGNED_LE");
 424 
 425                 } else if (AudioFormat.Encoding.PCM_SIGNED.equals(inputEncoding) && inputIsBigEndian &&
 426                            AudioFormat.Encoding.PCM_UNSIGNED.equals(outputEncoding) && !outputIsBigEndian) {
 427 
 428                     conversionType = PCM_SIGNED_BE2UNSIGNED_LE;
 429                     if(Printer.debug) Printer.debug("PCMtoPCMCodecStream: conversionType = PCM_SIGNED_BE2UNSIGNED_LE");
 430 
 431                 }
 432             }
 433 
 434             // set the audio stream length in frames if we know it
 435 
 436             frameSize = inputFormat.getFrameSize();
 437             if( frameSize == AudioSystem.NOT_SPECIFIED ) {
 438                 frameSize=1;
 439             }
 440             if( stream instanceof AudioInputStream ) {
 441                 frameLength = stream.getFrameLength();
 442             } else {
 443                 frameLength = AudioSystem.NOT_SPECIFIED;
 444             }
 445 
 446             // set framePos to zero
 447             framePos = 0;
 448 
 449         }
 450 
 451         /**
 452          * Note that this only works for sign conversions.
 453          * Other conversions require a read of at least 2 bytes.
 454          */
 455 
 456         public int read() throws IOException {
 457 
 458             // $$jb: do we want to implement this function?
 459 
 460             int temp;
 461             byte tempbyte;
 462 
 463             if( frameSize==1 ) {
 464                 if( conversionType == PCM_SWITCH_SIGNED_8BIT ) {
 465                     temp = super.read();
 466 
 467                     if( temp < 0 ) return temp;         // EOF or error
 468 
 469                     tempbyte = (byte) (temp & 0xf);
 470                     tempbyte = (tempbyte >= 0) ? (byte)(0x80 | tempbyte) : (byte)(0x7F & tempbyte);
 471                     temp = (int) tempbyte & 0xf;
 472 
 473                     return temp;
 474 
 475                 } else {
 476                     // $$jb: what to return here?
 477                     throw new IOException("cannot read a single byte if frame size > 1");
 478                 }
 479             } else {
 480                 throw new IOException("cannot read a single byte if frame size > 1");
 481             }
 482         }
 483 
 484 
 485         public int read(byte[] b) throws IOException {
 486 
 487             return read(b, 0, b.length);
 488         }
 489 
 490         public int read(byte[] b, int off, int len) throws IOException {
 491 
 492 
 493             int i;
 494 
 495             // don't read fractional frames
 496             if ( len%frameSize != 0 ) {
 497                 len -= (len%frameSize);
 498             }
 499             // don't read past our own set length
 500             if( (frameLength!=AudioSystem.NOT_SPECIFIED) && ( (len/frameSize) >(frameLength-framePos)) ) {
 501                 len = (int)(frameLength-framePos) * frameSize;
 502             }
 503 
 504             int readCount = super.read(b, off, len);
 505             byte tempByte;
 506 
 507             if(readCount<0) {   // EOF or error
 508                 return readCount;
 509             }
 510 
 511             // now do the conversions
 512 
 513             switch( conversionType ) {
 514 
 515             case PCM_SWITCH_SIGNED_8BIT:
 516                 switchSigned8bit(b,off,len,readCount);
 517                 break;
 518 
 519             case PCM_SWITCH_ENDIAN:
 520                 switchEndian(b,off,len,readCount);
 521                 break;
 522 
 523             case PCM_SWITCH_SIGNED_LE:
 524                 switchSignedLE(b,off,len,readCount);
 525                 break;
 526 
 527             case PCM_SWITCH_SIGNED_BE:
 528                 switchSignedBE(b,off,len,readCount);
 529                 break;
 530 
 531             case PCM_UNSIGNED_LE2SIGNED_BE:
 532             case PCM_SIGNED_LE2UNSIGNED_BE:
 533                 switchSignedLE(b,off,len,readCount);
 534                 switchEndian(b,off,len,readCount);
 535                 break;
 536 
 537             case PCM_UNSIGNED_BE2SIGNED_LE:
 538             case PCM_SIGNED_BE2UNSIGNED_LE:
 539                 switchSignedBE(b,off,len,readCount);
 540                 switchEndian(b,off,len,readCount);
 541                 break;
 542 
 543             default:
 544                                 // do nothing
 545             }
 546 
 547             // we've done the conversion, just return the readCount
 548             return readCount;
 549 
 550         }
 551 
 552         private void switchSigned8bit(byte[] b, int off, int len, int readCount) {
 553 
 554             for(int i=off; i < (off+readCount); i++) {
 555                 b[i] = (b[i] >= 0) ? (byte)(0x80 | b[i]) : (byte)(0x7F & b[i]);
 556             }
 557         }
 558 
 559         private void switchSignedBE(byte[] b, int off, int len, int readCount) {
 560 
 561             for(int i=off; i < (off+readCount); i+= sampleSizeInBytes ) {
 562                 b[i] = (b[i] >= 0) ? (byte)(0x80 | b[i]) : (byte)(0x7F & b[i]);
 563             }
 564         }
 565 
 566         private void switchSignedLE(byte[] b, int off, int len, int readCount) {
 567 
 568             for(int i=(off+sampleSizeInBytes-1); i < (off+readCount); i+= sampleSizeInBytes ) {
 569                 b[i] = (b[i] >= 0) ? (byte)(0x80 | b[i]) : (byte)(0x7F & b[i]);
 570             }
 571         }
 572 
 573         private void switchEndian(byte[] b, int off, int len, int readCount) {
 574 
 575             if(sampleSizeInBytes == 2) {
 576                 for(int i=off; i < (off+readCount); i += sampleSizeInBytes ) {
 577                     byte temp;
 578                     temp = b[i];
 579                     b[i] = b[i+1];
 580                     b[i+1] = temp;
 581                 }
 582             }
 583         }
 584 
 585 
 586 
 587     } // end class PCMtoPCMCodecStream
 588 
 589 } // end class PCMtoPCMCodec