WaveHeader.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.speech.srec;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class represents the header of a WAVE format audio file, which usually
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * have a .wav suffix.  The following integer valued fields are contained:
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> format - usually PCM, ALAW or ULAW.
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> numChannels - 1 for mono, 2 for stereo.
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> sampleRate - usually 8000, 11025, 16000, 22050, or 44100 hz.
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> bitsPerSample - usually 16 for PCM, 8 for ALAW, or 8 for ULAW.
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> numBytes - size of audio data after this header, in bytes.
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide pending API council approval
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WaveHeader {
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // follows WAVE format in http://ccrma.stanford.edu/courses/422/projects/WaveFormat
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "WaveHeader";
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int HEADER_LENGTH = 44;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Indicates PCM format. */
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final short FORMAT_PCM = 1;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Indicates ALAW format. */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final short FORMAT_ALAW = 6;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Indicates ULAW format. */
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final short FORMAT_ULAW = 7;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private short mFormat;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private short mNumChannels;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSampleRate;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private short mBitsPerSample;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumBytes;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Construct a WaveHeader, with all fields defaulting to zero.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader() {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Construct a WaveHeader, with fields initialized.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param format format of audio data,
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numChannels 1 for mono, 2 for stereo.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sampleRate typically 8000, 11025, 16000, 22050, or 44100 hz.
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bitsPerSample usually 16 for PCM, 8 for ULAW or 8 for ALAW.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numBytes size of audio data after this header, in bytes.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader(short format, short numChannels, int sampleRate, short bitsPerSample, int numBytes) {
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormat = format;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSampleRate = sampleRate;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumChannels = numChannels;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitsPerSample = bitsPerSample;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumBytes = numBytes;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the format field.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return format field,
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public short getFormat() {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFormat;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the format field.
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param format
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setFormat(short format) {
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormat = format;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the number of channels.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of channels, 1 for mono, 2 for stereo.
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public short getNumChannels() {
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNumChannels;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the number of channels.
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numChannels 1 for mono, 2 for stereo.
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setNumChannels(short numChannels) {
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumChannels = numChannels;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the sample rate.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSampleRate() {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mSampleRate;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the sample rate.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sampleRate sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setSampleRate(int sampleRate) {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSampleRate = sampleRate;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the number of bits per sample.
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of bits per sample,
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public short getBitsPerSample() {
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitsPerSample;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the number of bits per sample.
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bitsPerSample number of bits per sample,
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setBitsPerSample(short bitsPerSample) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitsPerSample = bitsPerSample;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the size of audio data after this header, in bytes.
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return size of audio data after this header, in bytes.
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNumBytes() {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNumBytes;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the size of audio data after this header, in bytes.
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numBytes size of audio data after this header, in bytes.
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setNumBytes(int numBytes) {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumBytes = numBytes;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Read and initialize a WaveHeader.
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param in {@link java.io.InputStream} to read from.
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of bytes consumed.
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IOException
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int read(InputStream in) throws IOException {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* RIFF header */
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "RIFF");
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numBytes = readInt(in) - 36;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "WAVE");
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* fmt chunk */
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "fmt ");
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (16 != readInt(in)) throw new IOException("fmt chunk length not 16");
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormat = readShort(in);
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumChannels = readShort(in);
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSampleRate = readInt(in);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int byteRate = readInt(in);
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        short blockAlign = readShort(in);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitsPerSample = readShort(in);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (byteRate != mNumChannels * mSampleRate * mBitsPerSample / 8) {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IOException("fmt.ByteRate field inconsistent");
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (blockAlign != mNumChannels * mBitsPerSample / 8) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IOException("fmt.BlockAlign field inconsistent");
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* data chunk */
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "data");
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumBytes = readInt(in);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return HEADER_LENGTH;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void readId(InputStream in, String id) throws IOException {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < id.length(); i++) {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (id.charAt(i) != in.read()) throw new IOException( id + " tag not present");
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int readInt(InputStream in) throws IOException {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return in.read() | (in.read() << 8) | (in.read() << 16) | (in.read() << 24);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static short readShort(InputStream in) throws IOException {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (short)(in.read() | (in.read() << 8));
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Write a WAVE file header.
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param out {@link java.io.OutputStream} to receive the header.
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of bytes written.
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IOException
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int write(OutputStream out) throws IOException {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* RIFF header */
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "RIFF");
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, 36 + mNumBytes);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "WAVE");
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* fmt chunk */
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "fmt ");
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, 16);
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, mFormat);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, mNumChannels);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, mSampleRate);
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, mNumChannels * mSampleRate * mBitsPerSample / 8);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, (short)(mNumChannels * mBitsPerSample / 8));
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, mBitsPerSample);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* data chunk */
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "data");
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, mNumBytes);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return HEADER_LENGTH;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void writeId(OutputStream out, String id) throws IOException {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < id.length(); i++) out.write(id.charAt(i));
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void writeInt(OutputStream out, int val) throws IOException {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 0);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 8);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 16);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 24);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void writeShort(OutputStream out, short val) throws IOException {
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 0);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 8);
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String.format(
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "WaveHeader format=%d numChannels=%d sampleRate=%d bitsPerSample=%d numBytes=%d",
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFormat, mNumChannels, mSampleRate, mBitsPerSample, mNumBytes);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
275