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