    public int read(byte[] b, int off, int len) throws IOException {
        int nSamples = len/frameSize;
        int totalRead = 0;
        int currentPos = off;
        do {
            int toRead = nSamples-totalRead;
            if (toRead > sampleBuf.length) toRead = sampleBuf.length;
            int nRead = source.getData(sampleBuf, 0, toRead);
            if (frameSize == 1) { 
                for (int i=0; i<nRead; i++, currentPos++) {
                    int sample = (int) (sampleBuf[i] * 128.0); 
                    b[currentPos] = (byte) ((sample>>8)&0xFF);
                }
            } else if (frameSize == 2){ 
                boolean bigEndian = format.isBigEndian();
                for (int i=0; i<nRead; i++, currentPos+=2) {
                    int sample = (int) (sampleBuf[i] * 32768.0); 
                    if (sample > MAX_AMPLITUDE || sample < -MAX_AMPLITUDE) {
                        System.err.println("Warning: signal amplitude out of range: "+sample);
                    }
                    byte hibyte = (byte) (sample>>8);
                    byte lobyte = (byte) (sample&0xFF);
                    if (!bigEndian) {
                        b[currentPos] = lobyte;
                        b[currentPos+1] = hibyte;
                    } else {
                        b[currentPos] = hibyte;
                        b[currentPos+1] = lobyte;
                    }
                }
            } else { 
                boolean bigEndian = format.isBigEndian();
                for (int i=0; i<nRead; i++, currentPos+=3) {
                    int sample = (int) (sampleBuf[i] * 8388606.0); 
                    byte hibyte = (byte) (sample>>16);
                    byte midbyte = (byte) ((sample>>8) & 0xFF);
                    byte lobyte = (byte) (sample&0xFF);
                    if (!bigEndian) {
                        b[currentPos] = lobyte;
                        b[currentPos+1] = midbyte;
                        b[currentPos+2] = hibyte;
                    } else {
                        b[currentPos] = hibyte;
                        b[currentPos+1] = midbyte;
                        b[currentPos+2] = lobyte;
                    }
                }
            }
            totalRead += nRead;
            assert currentPos <= off+len;
        } while (source.hasMoreData() && totalRead < nSamples);
        if (totalRead == 0) return -1;
        else return totalRead*frameSize;
    }

    public int read(byte[] b, int off, int len) throws IOException {
        int nSamples = len/frameSize;
        int totalRead = 0;
        int currentPos = off;
        do {
            int toRead = nSamples-totalRead;
            if (toRead > sampleBuf.length) toRead = sampleBuf.length;
            int nRead = source.getData(sampleBuf, 0, toRead);
            if (frameSize == 1) { 
                for (int i=0; i<nRead; i++, currentPos++) {
                    int sample = (int) Math.round(sampleBuf[i] * 127.0); 
                    b[currentPos] = (byte) ((sample>>8)&0xFF);
                }
            } else if (frameSize == 2){ 
                boolean bigEndian = format.isBigEndian();
                for (int i=0; i<nRead; i++, currentPos+=2) {
                    int sample = (int) Math.round(sampleBuf[i] * 32767.0); 
                    if (sample > MAX_AMPLITUDE || sample < -MAX_AMPLITUDE) {
                        System.err.println("Warning: signal amplitude out of range: "+sample);
                    }
                    byte hibyte = (byte) (sample>>8);
                    byte lobyte = (byte) (sample&0xFF);
                    if (!bigEndian) {
                        b[currentPos] = lobyte;
                        b[currentPos+1] = hibyte;
                    } else {
                        b[currentPos] = hibyte;
                        b[currentPos+1] = lobyte;
                    }
                }
            } else { 
                boolean bigEndian = format.isBigEndian();
                for (int i=0; i<nRead; i++, currentPos+=3) {
                    int sample = (int) Math.round(sampleBuf[i] * 8388605.0); 
                    byte hibyte = (byte) (sample>>16);
                    byte midbyte = (byte) ((sample>>8) & 0xFF);
                    byte lobyte = (byte) (sample&0xFF);
                    if (!bigEndian) {
                        b[currentPos] = lobyte;
                        b[currentPos+1] = midbyte;
                        b[currentPos+2] = hibyte;
                    } else {
                        b[currentPos] = hibyte;
                        b[currentPos+1] = midbyte;
                        b[currentPos+2] = lobyte;
                    }
                }
            }
            totalRead += nRead;
            assert currentPos <= off+len;
        } while (source.hasMoreData() && totalRead < nSamples);
        if (totalRead == 0) return -1;
        else return totalRead*frameSize;
    }
