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>
33935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn *
34935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn * Not yet ready to be supported, so
35935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn * @hide
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WaveHeader {
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // follows WAVE format in http://ccrma.stanford.edu/courses/422/projects/WaveFormat
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "WaveHeader";
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int HEADER_LENGTH = 44;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Indicates PCM format. */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final short FORMAT_PCM = 1;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Indicates ALAW format. */
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final short FORMAT_ALAW = 6;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Indicates ULAW format. */
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final short FORMAT_ULAW = 7;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private short mFormat;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private short mNumChannels;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSampleRate;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private short mBitsPerSample;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumBytes;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Construct a WaveHeader, with all fields defaulting to zero.
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader() {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Construct a WaveHeader, with fields initialized.
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param format format of audio data,
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numChannels 1 for mono, 2 for stereo.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sampleRate typically 8000, 11025, 16000, 22050, or 44100 hz.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bitsPerSample usually 16 for PCM, 8 for ULAW or 8 for ALAW.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numBytes size of audio data after this header, in bytes.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader(short format, short numChannels, int sampleRate, short bitsPerSample, int numBytes) {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormat = format;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSampleRate = sampleRate;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumChannels = numChannels;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitsPerSample = bitsPerSample;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumBytes = numBytes;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the format field.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return format field,
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public short getFormat() {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFormat;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the format field.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param format
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setFormat(short format) {
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormat = format;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the number of channels.
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of channels, 1 for mono, 2 for stereo.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public short getNumChannels() {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNumChannels;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the number of channels.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numChannels 1 for mono, 2 for stereo.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setNumChannels(short numChannels) {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumChannels = numChannels;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the sample rate.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSampleRate() {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mSampleRate;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the sample rate.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sampleRate sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setSampleRate(int sampleRate) {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSampleRate = sampleRate;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the number of bits per sample.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of bits per sample,
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public short getBitsPerSample() {
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitsPerSample;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the number of bits per sample.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bitsPerSample number of bits per sample,
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setBitsPerSample(short bitsPerSample) {
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitsPerSample = bitsPerSample;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the size of audio data after this header, in bytes.
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return size of audio data after this header, in bytes.
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNumBytes() {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNumBytes;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the size of audio data after this header, in bytes.
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numBytes size of audio data after this header, in bytes.
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return reference to this WaveHeader instance.
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public WaveHeader setNumBytes(int numBytes) {
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumBytes = numBytes;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Read and initialize a WaveHeader.
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param in {@link java.io.InputStream} to read from.
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of bytes consumed.
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IOException
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int read(InputStream in) throws IOException {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* RIFF header */
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "RIFF");
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numBytes = readInt(in) - 36;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "WAVE");
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* fmt chunk */
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "fmt ");
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (16 != readInt(in)) throw new IOException("fmt chunk length not 16");
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormat = readShort(in);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumChannels = readShort(in);
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSampleRate = readInt(in);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int byteRate = readInt(in);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        short blockAlign = readShort(in);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitsPerSample = readShort(in);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (byteRate != mNumChannels * mSampleRate * mBitsPerSample / 8) {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IOException("fmt.ByteRate field inconsistent");
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (blockAlign != mNumChannels * mBitsPerSample / 8) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IOException("fmt.BlockAlign field inconsistent");
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* data chunk */
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        readId(in, "data");
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumBytes = readInt(in);
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return HEADER_LENGTH;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void readId(InputStream in, String id) throws IOException {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < id.length(); i++) {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (id.charAt(i) != in.read()) throw new IOException( id + " tag not present");
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int readInt(InputStream in) throws IOException {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return in.read() | (in.read() << 8) | (in.read() << 16) | (in.read() << 24);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static short readShort(InputStream in) throws IOException {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (short)(in.read() | (in.read() << 8));
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Write a WAVE file header.
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param out {@link java.io.OutputStream} to receive the header.
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return number of bytes written.
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IOException
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int write(OutputStream out) throws IOException {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* RIFF header */
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "RIFF");
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, 36 + mNumBytes);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "WAVE");
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* fmt chunk */
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "fmt ");
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, 16);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, mFormat);
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, mNumChannels);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, mSampleRate);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, mNumChannels * mSampleRate * mBitsPerSample / 8);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, (short)(mNumChannels * mBitsPerSample / 8));
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeShort(out, mBitsPerSample);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* data chunk */
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeId(out, "data");
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        writeInt(out, mNumBytes);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return HEADER_LENGTH;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void writeId(OutputStream out, String id) throws IOException {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < id.length(); i++) out.write(id.charAt(i));
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void writeInt(OutputStream out, int val) throws IOException {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 0);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 8);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 16);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 24);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void writeShort(OutputStream out, short val) throws IOException {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 0);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.write(val >> 8);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String.format(
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "WaveHeader format=%d numChannels=%d sampleRate=%d bitsPerSample=%d numBytes=%d",
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFormat, mNumChannels, mSampleRate, mBitsPerSample, mNumBytes);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
277