plectrum

Plectrum: instrument tuner for Android
Log | Files | Refs | README | LICENSE

WaveHeader.java (8105B)


      1 package be.tarsos.dsp.writer;
      2 
      3 import java.io.IOException;
      4 import java.io.InputStream;
      5 import java.io.OutputStream;
      6 
      7 /**
      8  * this source code is copied from : https://android.googlesource.com/platform/frameworks/base.git/+/android-4.3_r2/core/java/android/speech/srec/WaveHeader.java
      9  */
     10 /**
     11  * This class represents the header of a WAVE format audio file, which usually
     12  * have a .wav suffix.  The following integer valued fields are contained:
     13  * <ul>
     14  * <li> format - usually PCM, ALAW or ULAW.
     15  * <li> numChannels - 1 for mono, 2 for stereo.
     16  * <li> sampleRate - usually 8000, 11025, 16000, 22050, or 44100 hz.
     17  * <li> bitsPerSample - usually 16 for PCM, 8 for ALAW, or 8 for ULAW.
     18  * <li> numBytes - size of audio data after this header, in bytes.
     19  * </ul>
     20  *
     21  * Not yet ready to be supported, so
     22  * @hide
     23  */
     24 public class WaveHeader {
     25 
     26     // follows WAVE format in http://ccrma.stanford.edu/courses/422/projects/WaveFormat
     27 
     28     private static final int HEADER_LENGTH = 44;
     29 
     30     /** Indicates PCM format. */
     31     public static final short FORMAT_PCM = 1;
     32     /** Indicates ALAW format. */
     33     public static final short FORMAT_ALAW = 6;
     34     /** Indicates ULAW format. */
     35     public static final short FORMAT_ULAW = 7;
     36 
     37     private short mFormat;
     38     private short mNumChannels;
     39     private int mSampleRate;
     40     private short mBitsPerSample;
     41     private int mNumBytes;
     42 
     43     /**
     44      * Construct a WaveHeader, with all fields defaulting to zero.
     45      */
     46     public WaveHeader() {
     47     }
     48 
     49     /**
     50      * Construct a WaveHeader, with fields initialized.
     51      * @param format format of audio data,
     52      * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
     53      * @param numChannels 1 for mono, 2 for stereo.
     54      * @param sampleRate typically 8000, 11025, 16000, 22050, or 44100 hz.
     55      * @param bitsPerSample usually 16 for PCM, 8 for ULAW or 8 for ALAW.
     56      * @param numBytes size of audio data after this header, in bytes.
     57      */
     58     public WaveHeader(short format, short numChannels, int sampleRate, short bitsPerSample, int numBytes) {
     59         mFormat = format;
     60         mSampleRate = sampleRate;
     61         mNumChannels = numChannels;
     62         mBitsPerSample = bitsPerSample;
     63         mNumBytes = numBytes;
     64     }
     65 
     66     /**
     67      * Get the format field.
     68      * @return format field,
     69      * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
     70      */
     71     public short getFormat() {
     72         return mFormat;
     73     }
     74 
     75     /**
     76      * Set the format field.
     77      * @param format
     78      * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
     79      * @return reference to this WaveHeader instance.
     80      */
     81     public WaveHeader setFormat(short format) {
     82         mFormat = format;
     83         return this;
     84     }
     85 
     86     /**
     87      * Get the number of channels.
     88      * @return number of channels, 1 for mono, 2 for stereo.
     89      */
     90     public short getNumChannels() {
     91         return mNumChannels;
     92     }
     93 
     94     /**
     95      * Set the number of channels.
     96      * @param numChannels 1 for mono, 2 for stereo.
     97      * @return reference to this WaveHeader instance.
     98      */
     99     public WaveHeader setNumChannels(short numChannels) {
    100         mNumChannels = numChannels;
    101         return this;
    102     }
    103 
    104     /**
    105      * Get the sample rate.
    106      * @return sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
    107      */
    108     public int getSampleRate() {
    109         return mSampleRate;
    110     }
    111 
    112     /**
    113      * Set the sample rate.
    114      * @param sampleRate sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
    115      * @return reference to this WaveHeader instance.
    116      */
    117     public WaveHeader setSampleRate(int sampleRate) {
    118         mSampleRate = sampleRate;
    119         return this;
    120     }
    121 
    122     /**
    123      * Get the number of bits per sample.
    124      * @return number of bits per sample,
    125      * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
    126      */
    127     public short getBitsPerSample() {
    128         return mBitsPerSample;
    129     }
    130 
    131     /**
    132      * Set the number of bits per sample.
    133      * @param bitsPerSample number of bits per sample,
    134      * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
    135      * @return reference to this WaveHeader instance.
    136      */
    137     public WaveHeader setBitsPerSample(short bitsPerSample) {
    138         mBitsPerSample = bitsPerSample;
    139         return this;
    140     }
    141 
    142     /**
    143      * Get the size of audio data after this header, in bytes.
    144      * @return size of audio data after this header, in bytes.
    145      */
    146     public int getNumBytes() {
    147         return mNumBytes;
    148     }
    149 
    150     /**
    151      * Set the size of audio data after this header, in bytes.
    152      * @param numBytes size of audio data after this header, in bytes.
    153      * @return reference to this WaveHeader instance.
    154      */
    155     public WaveHeader setNumBytes(int numBytes) {
    156         mNumBytes = numBytes;
    157         return this;
    158     }
    159 
    160     /**
    161      * Read and initialize a WaveHeader.
    162      * @param in {@link java.io.InputStream} to read from.
    163      * @return number of bytes consumed.
    164      * @throws IOException
    165      */
    166     public int read(InputStream in) throws IOException {
    167         /* RIFF header */
    168         readId(in, "RIFF");
    169         
    170         readId(in, "WAVE");
    171 
    172         /* fmt chunk */
    173         readId(in, "fmt ");
    174         if (16 != readInt(in)) throw new IOException("fmt chunk length not 16");
    175         mFormat = readShort(in);
    176         mNumChannels = readShort(in);
    177         mSampleRate = readInt(in);
    178         int byteRate = readInt(in);
    179         short blockAlign = readShort(in);
    180         mBitsPerSample = readShort(in);
    181         if (byteRate != mNumChannels * mSampleRate * mBitsPerSample / 8) {
    182             throw new IOException("fmt.ByteRate field inconsistent");
    183         }
    184         if (blockAlign != mNumChannels * mBitsPerSample / 8) {
    185             throw new IOException("fmt.BlockAlign field inconsistent");
    186         }
    187 
    188         /* data chunk */
    189         readId(in, "data");
    190         mNumBytes = readInt(in);
    191 
    192         return HEADER_LENGTH;
    193     }
    194 
    195     private static void readId(InputStream in, String id) throws IOException {
    196         for (int i = 0; i < id.length(); i++) {
    197             if (id.charAt(i) != in.read()) throw new IOException( id + " tag not present");
    198         }
    199     }
    200 
    201     private static int readInt(InputStream in) throws IOException {
    202         return in.read() | (in.read() << 8) | (in.read() << 16) | (in.read() << 24);
    203     }
    204 
    205     private static short readShort(InputStream in) throws IOException {
    206         return (short)(in.read() | (in.read() << 8));
    207     }
    208 
    209     /**
    210      * Write a WAVE file header.
    211      * @param out {@link java.io.OutputStream} to receive the header.
    212      * @return number of bytes written.
    213      * @throws IOException
    214      */
    215     public int write(OutputStream out) throws IOException {
    216         /* RIFF header */
    217         writeId(out, "RIFF");
    218         writeInt(out, 36 + mNumBytes);
    219         writeId(out, "WAVE");
    220 
    221         /* fmt chunk */
    222         writeId(out, "fmt ");
    223         writeInt(out, 16);
    224         writeShort(out, mFormat);
    225         writeShort(out, mNumChannels);
    226         writeInt(out, mSampleRate);
    227         writeInt(out, mNumChannels * mSampleRate * mBitsPerSample / 8);
    228         writeShort(out, (short)(mNumChannels * mBitsPerSample / 8));
    229         writeShort(out, mBitsPerSample);
    230 
    231         /* data chunk */
    232         writeId(out, "data");
    233         writeInt(out, mNumBytes);
    234 
    235         return HEADER_LENGTH;
    236     }
    237 
    238     private static void writeId(OutputStream out, String id) throws IOException {
    239         for (int i = 0; i < id.length(); i++) out.write(id.charAt(i));
    240     }
    241 
    242     private static void writeInt(OutputStream out, int val) throws IOException {
    243         out.write(val >> 0);
    244         out.write(val >> 8);
    245         out.write(val >> 16);
    246         out.write(val >> 24);
    247     }
    248 
    249     private static void writeShort(OutputStream out, short val) throws IOException {
    250         out.write(val >> 0);
    251         out.write(val >> 8);
    252     }
    253 
    254     @Override
    255     public String toString() {
    256         return String.format(
    257                 "WaveHeader format=%d numChannels=%d sampleRate=%d bitsPerSample=%d numBytes=%d",
    258                 mFormat, mNumChannels, mSampleRate, mBitsPerSample, mNumBytes);
    259     }
    260 
    261 }