1 /* WAVReader.java -- Read WAV files.
2 Copyright (C) 2006, 2012 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu
.javax
.sound
.sampled
.WAV
;
41 import java
.io
.IOException
;
42 import java
.io
.InputStream
;
43 import java
.io
.DataInputStream
;
44 import java
.io
.FileInputStream
;
47 import javax
.sound
.sampled
.AudioFormat
;
48 import javax
.sound
.sampled
.AudioFileFormat
;
49 import javax
.sound
.sampled
.AudioInputStream
;
50 import javax
.sound
.sampled
.UnsupportedAudioFileException
;
51 import javax
.sound
.sampled
.spi
.AudioFileReader
;
56 * This code reads WAV files.
58 * There are many decent documents on the web describing the WAV file
59 * format. I didn't bother looking for the official document. If it
60 * exists, I'm not even sure if it is freely available. We should
61 * update this comment if we find out anything helpful here. I used
62 * http://www.sonicspot.com/guide/wavefiles.html
64 * @author Anthony Green (green@redhat.com)
67 public class WAVReader
extends AudioFileReader
69 private static long readUnsignedIntLE (DataInputStream is
)
72 byte[] buf
= new byte[4];
75 | ((buf
[1] & 0xFF) << 8)
76 | ((buf
[2] & 0xFF) << 16)
77 | ((buf
[3] & 0xFF) << 24));
80 private static short readUnsignedShortLE (DataInputStream is
)
83 byte[] buf
= new byte[2];
85 return (short) (buf
[0] & 0xFF
86 | ((buf
[1] & 0xFF) << 8));
89 /* Get an AudioFileFormat from the given File.
90 * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.io.File)
92 public AudioFileFormat
getAudioFileFormat(File file
)
93 throws UnsupportedAudioFileException
, IOException
95 InputStream is
= new FileInputStream(file
);
98 return getAudioFileFormat(is
);
106 /* Get an AudioFileFormat from the given InputStream.
107 * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.io.InputStream)
109 public AudioFileFormat
getAudioFileFormat(InputStream in
)
110 throws UnsupportedAudioFileException
, IOException
114 if (in
instanceof DataInputStream
)
115 din
= (DataInputStream
) in
;
117 din
= new DataInputStream(in
);
119 if (din
.readInt() != 0x52494646) // "RIFF"
120 throw new UnsupportedAudioFileException("Invalid WAV chunk header.");
122 // Read the length of this RIFF thing.
123 readUnsignedIntLE(din
);
125 if (din
.readInt() != 0x57415645) // "WAVE"
126 throw new UnsupportedAudioFileException("Invalid WAV chunk header.");
128 boolean foundFmt
= false;
129 boolean foundData
= false;
131 short compressionCode
= 0, numberChannels
= 0, bitsPerSample
= 0;
132 long sampleRate
= 0, bytesPerSecond
= 0;
133 long chunkLength
= 0;
137 int chunkId
= din
.readInt();
138 chunkLength
= readUnsignedIntLE(din
);
141 case 0x666D7420: // "fmt "
143 compressionCode
= readUnsignedShortLE(din
);
144 numberChannels
= readUnsignedShortLE(din
);
145 sampleRate
= readUnsignedIntLE(din
);
146 bytesPerSecond
= readUnsignedIntLE(din
);
147 readUnsignedShortLE(din
); // blockAlign
148 bitsPerSample
= readUnsignedShortLE(din
);
149 din
.skip(chunkLength
- 16);
151 case 0x66616374: // "fact"
152 // FIXME: hold compression format dependent data.
153 din
.skip(chunkLength
);
155 case 0x64617461: // "data"
157 throw new UnsupportedAudioFileException("This implementation requires WAV fmt chunks precede data chunks.");
161 // Unrecognized chunk. Skip it.
162 din
.skip(chunkLength
);
166 AudioFormat
.Encoding encoding
;
168 switch (compressionCode
)
170 case 1: // PCM/uncompressed
171 if (bitsPerSample
<= 8)
172 encoding
= AudioFormat
.Encoding
.PCM_UNSIGNED
;
174 encoding
= AudioFormat
.Encoding
.PCM_SIGNED
;
178 throw new UnsupportedAudioFileException("Unrecognized WAV compression code: 0x"
179 + Integer
.toHexString(compressionCode
));
182 return new AudioFileFormat (AudioFileFormat
.Type
.WAVE
,
183 new AudioFormat(encoding
,
187 ((bitsPerSample
+ 7) / 8) * numberChannels
,
188 (float) bytesPerSecond
, false),
192 /* Get an AudioFileFormat from the given URL.
193 * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.net.URL)
195 public AudioFileFormat
getAudioFileFormat(URL url
)
196 throws UnsupportedAudioFileException
, IOException
198 InputStream is
= url
.openStream();
201 return getAudioFileFormat(is
);
209 /* Get an AudioInputStream from the given File.
210 * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.io.File)
212 public AudioInputStream
getAudioInputStream(File file
)
213 throws UnsupportedAudioFileException
, IOException
215 return getAudioInputStream(new FileInputStream(file
));
218 /* Get an AudioInputStream from the given InputStream.
219 * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.io.InputStream)
221 public AudioInputStream
getAudioInputStream(InputStream stream
)
222 throws UnsupportedAudioFileException
, IOException
224 AudioFileFormat aff
= getAudioFileFormat(stream
);
225 return new AudioInputStream(stream
, aff
.getFormat(), (long) aff
.getFrameLength());
228 /* Get an AudioInputStream from the given URL.
229 * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.net.URL)
231 public AudioInputStream
getAudioInputStream(URL url
)
232 throws UnsupportedAudioFileException
, IOException
234 return getAudioInputStream(url
.openStream());