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