34 import java.net.URL; 35 36 import javax.sound.sampled.AudioFileFormat; 37 import javax.sound.sampled.AudioFormat; 38 import javax.sound.sampled.AudioInputStream; 39 import javax.sound.sampled.AudioSystem; 40 import javax.sound.sampled.UnsupportedAudioFileException; 41 42 43 /** 44 * AIFF file reader and writer. 45 * 46 * @author Kara Kytle 47 * @author Jan Borgersen 48 * @author Florian Bomers 49 */ 50 public final class AiffFileReader extends SunFileReader { 51 52 private static final int MAX_READ_LENGTH = 8; 53 54 /** 55 * Constructs a new AiffParser object. 56 */ 57 public AiffFileReader() { 58 } 59 60 61 62 63 // METHODS TO IMPLEMENT AudioFileReader 64 65 /** 66 * Obtains the audio file format of the input stream provided. The stream must 67 * point to valid audio file data. In general, audio file providers may 68 * need to read some data from the stream before determining whether they 69 * support it. These parsers must 70 * be able to mark the stream, read enough data to determine whether they 71 * support the stream, and, if not, reset the stream's read pointer to its original 72 * position. If the input stream does not support this, this method may fail 73 * with an IOException. 74 * @param stream the input stream from which file format information should be 75 * extracted 76 * @return an <code>AudioFileFormat</code> object describing the audio file format 77 * @throws UnsupportedAudioFileException if the stream does not point to valid audio 78 * file data recognized by the system 79 * @throws IOException if an I/O exception occurs 80 * @see InputStream#markSupported 81 * @see InputStream#mark 82 */ 275 // Read the chunk name 276 int chunkName = dis.readInt(); 277 int chunkLen = dis.readInt(); 278 fileRead += 8; 279 280 int chunkRead = 0; 281 282 // Switch on the chunk name. 283 switch (chunkName) { 284 case AiffFileFormat.FVER_MAGIC: 285 // Ignore format version for now. 286 break; 287 288 case AiffFileFormat.COMM_MAGIC: 289 // AIFF vs. AIFC 290 // $$fb: fix for 4399551: Repost of bug candidate: cannot replay aif file (Review ID: 108108) 291 if ((!aifc && chunkLen < 18) || (aifc && chunkLen < 22)) { 292 throw new UnsupportedAudioFileException("Invalid AIFF/COMM chunksize"); 293 } 294 // Read header info. 295 int channels = dis.readShort(); 296 dis.readInt(); 297 int sampleSizeInBits = dis.readShort(); 298 float sampleRate = (float) read_ieee_extended(dis); 299 chunkRead += (2 + 4 + 2 + 10); 300 301 // If this is not AIFC then we assume it's 302 // a linearly encoded file. 303 AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED; 304 305 if (aifc) { 306 int enc = dis.readInt(); chunkRead += 4; 307 switch (enc) { 308 case AiffFileFormat.AIFC_PCM: 309 encoding = AudioFormat.Encoding.PCM_SIGNED; 310 break; 311 case AiffFileFormat.AIFC_ULAW: 312 encoding = AudioFormat.Encoding.ULAW; 313 sampleSizeInBits = 8; // Java Sound convention 314 break; 315 default: 316 throw new UnsupportedAudioFileException("Invalid AIFF encoding"); 317 } 421 t1 = (long)dis.readUnsignedShort(); 422 t2 = (long)dis.readUnsignedShort(); 423 loMant = t1 << 16 | t2; 424 425 if (expon == 0 && hiMant == 0 && loMant == 0) { 426 f = 0; 427 } else { 428 if (expon == 0x7FFF) 429 f = HUGE; 430 else { 431 expon -= 16383; 432 expon -= 31; 433 f = (hiMant * Math.pow(2, expon)); 434 expon -= 32; 435 f += (loMant * Math.pow(2, expon)); 436 } 437 } 438 439 return f; 440 } 441 442 443 444 } | 34 import java.net.URL; 35 36 import javax.sound.sampled.AudioFileFormat; 37 import javax.sound.sampled.AudioFormat; 38 import javax.sound.sampled.AudioInputStream; 39 import javax.sound.sampled.AudioSystem; 40 import javax.sound.sampled.UnsupportedAudioFileException; 41 42 43 /** 44 * AIFF file reader and writer. 45 * 46 * @author Kara Kytle 47 * @author Jan Borgersen 48 * @author Florian Bomers 49 */ 50 public final class AiffFileReader extends SunFileReader { 51 52 private static final int MAX_READ_LENGTH = 8; 53 54 // METHODS TO IMPLEMENT AudioFileReader 55 56 /** 57 * Obtains the audio file format of the input stream provided. The stream must 58 * point to valid audio file data. In general, audio file providers may 59 * need to read some data from the stream before determining whether they 60 * support it. These parsers must 61 * be able to mark the stream, read enough data to determine whether they 62 * support the stream, and, if not, reset the stream's read pointer to its original 63 * position. If the input stream does not support this, this method may fail 64 * with an IOException. 65 * @param stream the input stream from which file format information should be 66 * extracted 67 * @return an <code>AudioFileFormat</code> object describing the audio file format 68 * @throws UnsupportedAudioFileException if the stream does not point to valid audio 69 * file data recognized by the system 70 * @throws IOException if an I/O exception occurs 71 * @see InputStream#markSupported 72 * @see InputStream#mark 73 */ 266 // Read the chunk name 267 int chunkName = dis.readInt(); 268 int chunkLen = dis.readInt(); 269 fileRead += 8; 270 271 int chunkRead = 0; 272 273 // Switch on the chunk name. 274 switch (chunkName) { 275 case AiffFileFormat.FVER_MAGIC: 276 // Ignore format version for now. 277 break; 278 279 case AiffFileFormat.COMM_MAGIC: 280 // AIFF vs. AIFC 281 // $$fb: fix for 4399551: Repost of bug candidate: cannot replay aif file (Review ID: 108108) 282 if ((!aifc && chunkLen < 18) || (aifc && chunkLen < 22)) { 283 throw new UnsupportedAudioFileException("Invalid AIFF/COMM chunksize"); 284 } 285 // Read header info. 286 short channels = dis.readShort(); 287 if (channels <= 0) { 288 throw new UnsupportedAudioFileException("Invalid number of channels"); 289 } 290 dis.readInt(); // numSampleFrames 291 short sampleSizeInBits = dis.readShort(); 292 if (sampleSizeInBits < 1 || sampleSizeInBits > 32) { 293 throw new UnsupportedAudioFileException("Invalid AIFF/COMM sampleSize"); 294 } 295 float sampleRate = (float) read_ieee_extended(dis); 296 chunkRead += (2 + 4 + 2 + 10); 297 298 // If this is not AIFC then we assume it's 299 // a linearly encoded file. 300 AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED; 301 302 if (aifc) { 303 int enc = dis.readInt(); chunkRead += 4; 304 switch (enc) { 305 case AiffFileFormat.AIFC_PCM: 306 encoding = AudioFormat.Encoding.PCM_SIGNED; 307 break; 308 case AiffFileFormat.AIFC_ULAW: 309 encoding = AudioFormat.Encoding.ULAW; 310 sampleSizeInBits = 8; // Java Sound convention 311 break; 312 default: 313 throw new UnsupportedAudioFileException("Invalid AIFF encoding"); 314 } 418 t1 = (long)dis.readUnsignedShort(); 419 t2 = (long)dis.readUnsignedShort(); 420 loMant = t1 << 16 | t2; 421 422 if (expon == 0 && hiMant == 0 && loMant == 0) { 423 f = 0; 424 } else { 425 if (expon == 0x7FFF) 426 f = HUGE; 427 else { 428 expon -= 16383; 429 expon -= 31; 430 f = (hiMant * Math.pow(2, expon)); 431 expon -= 32; 432 f += (loMant * Math.pow(2, expon)); 433 } 434 } 435 436 return f; 437 } 438 } |