< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java

Print this page




  42 import javax.sound.sampled.AudioFormat;
  43 import javax.sound.sampled.AudioInputStream;
  44 import javax.sound.sampled.AudioSystem;
  45 
  46 //$$fb this class is buggy. Should be replaced in future.
  47 
  48 /**
  49  * AIFF file writer.
  50  *
  51  * @author Jan Borgersen
  52  */
  53 public final class AiffFileWriter extends SunFileWriter {
  54 
  55     /**
  56      * Constructs a new AiffFileWriter object.
  57      */
  58     public AiffFileWriter() {
  59         super(new AudioFileFormat.Type[]{AudioFileFormat.Type.AIFF});
  60     }
  61 
  62 
  63     // METHODS TO IMPLEMENT AudioFileWriter
  64 
  65     @Override
  66     public AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream) {
  67 
  68         AudioFileFormat.Type[] filetypes = new AudioFileFormat.Type[types.length];
  69         System.arraycopy(types, 0, filetypes, 0, types.length);
  70 
  71         // make sure we can write this stream
  72         AudioFormat format = stream.getFormat();
  73         AudioFormat.Encoding encoding = format.getEncoding();
  74 
  75         if( (AudioFormat.Encoding.ALAW.equals(encoding)) ||
  76             (AudioFormat.Encoding.ULAW.equals(encoding)) ||
  77             (AudioFormat.Encoding.PCM_SIGNED.equals(encoding)) ||
  78             (AudioFormat.Encoding.PCM_UNSIGNED.equals(encoding)) ) {
  79 
  80             return filetypes;
  81         }
  82 
  83         return new AudioFileFormat.Type[0];
  84     }
  85 
  86 
  87     @Override
  88     public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException {
  89         Objects.requireNonNull(stream);
  90         Objects.requireNonNull(fileType);
  91         Objects.requireNonNull(out);
  92 
  93         //$$fb the following check must come first ! Otherwise
  94         // the next frame length check may throw an IOException and
  95         // interrupt iterating File Writers. (see bug 4351296)
  96 
  97         // throws IllegalArgumentException if not supported
  98         AiffFileFormat aiffFileFormat = (AiffFileFormat)getAudioFileFormat(fileType, stream);
  99 
 100         // we must know the total data length to calculate the file length
 101         if( stream.getFrameLength() == AudioSystem.NOT_SPECIFIED ) {
 102             throw new IOException("stream length not specified");
 103         }
 104 
 105         int bytesWritten = writeAiffFile(stream, aiffFileFormat, out);
 106         return bytesWritten;
 107     }
 108 
 109 
 110     @Override
 111     public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException {
 112         Objects.requireNonNull(stream);
 113         Objects.requireNonNull(fileType);
 114         Objects.requireNonNull(out);
 115 
 116         // throws IllegalArgumentException if not supported
 117         AiffFileFormat aiffFileFormat = (AiffFileFormat)getAudioFileFormat(fileType, stream);
 118 
 119         // first write the file without worrying about length fields
 120         FileOutputStream fos = new FileOutputStream( out );     // throws IOException
 121         BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize );
 122         int bytesWritten = writeAiffFile(stream, aiffFileFormat, bos );
 123         bos.close();
 124 
 125         // now, if length fields were not specified, calculate them,
 126         // open as a random access file, write the appropriate fields,
 127         // close again....
 128         if( aiffFileFormat.getByteLength()== AudioSystem.NOT_SPECIFIED ) {
 129 
 130             // $$kk: 10.22.99: jan: please either implement this or throw an exception!
 131             // $$fb: 2001-07-13: done. Fixes Bug 4479981
 132             int ssndBlockSize           = (aiffFileFormat.getFormat().getChannels() * aiffFileFormat.getFormat().getSampleSizeInBits());


 133 
 134             int aiffLength=bytesWritten;
 135             int ssndChunkSize=aiffLength-aiffFileFormat.getHeaderSize()+16;
 136             long dataSize=ssndChunkSize-16;
 137             int numFrames=(int) (dataSize*8/ssndBlockSize);

 138 
 139             RandomAccessFile raf=new RandomAccessFile(out, "rw");
 140             // skip FORM magic
 141             raf.skipBytes(4);
 142             raf.writeInt(aiffLength-8);
 143             // skip aiff2 magic, fver chunk, comm magic, comm size, channel count,
 144             raf.skipBytes(4+aiffFileFormat.getFverChunkSize()+4+4+2);
 145             // write frame count
 146             raf.writeInt(numFrames);
 147             // skip sample size, samplerate, SSND magic
 148             raf.skipBytes(2+10+4);
 149             raf.writeInt(ssndChunkSize-8);
 150             // that's all
 151             raf.close();
 152         }
 153 
 154         return bytesWritten;
 155     }
 156 
 157 
 158     // -----------------------------------------------------------------------
 159 
 160     /**
 161      * Returns the AudioFileFormat describing the file that will be written from this AudioInputStream.
 162      * Throws IllegalArgumentException if not supported.
 163      */
 164     private AudioFileFormat getAudioFileFormat(AudioFileFormat.Type type, AudioInputStream stream) {
 165         if (!isFileTypeSupported(type, stream)) {
 166             throw new IllegalArgumentException("File type " + type + " not supported.");
 167         }
 168 
 169         AudioFormat format = null;
 170         AiffFileFormat fileFormat = null;
 171         AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
 172 
 173         AudioFormat streamFormat = stream.getFormat();
 174         AudioFormat.Encoding streamEncoding = streamFormat.getEncoding();
 175 
 176 
 177         float sampleRate;
 178         int sampleSizeInBits;
 179         int channels;
 180         int frameSize;
 181         float frameRate;
 182         int fileSize;
 183         boolean convert8to16 = false;
 184 
 185         if( (AudioFormat.Encoding.ALAW.equals(streamEncoding)) ||
 186             (AudioFormat.Encoding.ULAW.equals(streamEncoding)) ) {
 187 
 188             if( streamFormat.getSampleSizeInBits()==8 ) {
 189 
 190                 encoding = AudioFormat.Encoding.PCM_SIGNED;
 191                 sampleSizeInBits=16;
 192                 convert8to16 = true;
 193 
 194             } else {
 195 
 196                 // can't convert non-8-bit ALAW,ULAW
 197                 throw new IllegalArgumentException("Encoding " + streamEncoding + " supported only for 8-bit data.");
 198             }
 199         } else if ( streamFormat.getSampleSizeInBits()==8 ) {
 200 
 201             encoding = AudioFormat.Encoding.PCM_UNSIGNED;


 218 
 219 
 220         if( stream.getFrameLength()!=AudioSystem.NOT_SPECIFIED ) {
 221             if( convert8to16 ) {
 222                 fileSize = (int)stream.getFrameLength()*streamFormat.getFrameSize()*2 + AiffFileFormat.AIFF_HEADERSIZE;
 223             } else {
 224                 fileSize = (int)stream.getFrameLength()*streamFormat.getFrameSize() + AiffFileFormat.AIFF_HEADERSIZE;
 225             }
 226         } else {
 227             fileSize = AudioSystem.NOT_SPECIFIED;
 228         }
 229 
 230         fileFormat = new AiffFileFormat( AudioFileFormat.Type.AIFF,
 231                                          fileSize,
 232                                          format,
 233                                          (int)stream.getFrameLength() );
 234 
 235         return fileFormat;
 236     }
 237 
 238 
 239     private int writeAiffFile(InputStream in, AiffFileFormat aiffFileFormat, OutputStream out) throws IOException {
 240 
 241         int bytesRead = 0;
 242         int bytesWritten = 0;
 243         InputStream fileStream = getFileStream(aiffFileFormat, in);
 244         byte buffer[] = new byte[bisBufferSize];
 245         int maxLength = aiffFileFormat.getByteLength();
 246 
 247         while( (bytesRead = fileStream.read( buffer )) >= 0 ) {
 248             if (maxLength>0) {
 249                 if( bytesRead < maxLength ) {
 250                     out.write( buffer, 0, bytesRead );
 251                     bytesWritten += bytesRead;
 252                     maxLength -= bytesRead;
 253                 } else {
 254                     out.write( buffer, 0, maxLength );
 255                     bytesWritten += maxLength;
 256                     maxLength = 0;
 257                     break;
 258                 }
 259 
 260             } else {
 261                 out.write( buffer, 0, bytesRead );
 262                 bytesWritten += bytesRead;
 263             }
 264         }
 265 
 266         return bytesWritten;
 267     }
 268 
 269     private InputStream getFileStream(AiffFileFormat aiffFileFormat, InputStream audioStream) throws IOException  {
 270 
 271         // private method ... assumes aiffFileFormat is a supported file format
 272 
 273         AudioFormat format = aiffFileFormat.getFormat();
 274         AudioFormat streamFormat = null;
 275         AudioFormat.Encoding encoding = null;
 276 
 277         //$$fb a little bit nicer handling of constants
 278 
 279         //int headerSize          = 54;
 280         int headerSize          = aiffFileFormat.getHeaderSize();
 281 
 282         //int fverChunkSize       = 0;
 283         int fverChunkSize       = aiffFileFormat.getFverChunkSize();
 284         //int commChunkSize       = 26;
 285         int commChunkSize       = aiffFileFormat.getCommChunkSize();
 286         int aiffLength          = -1;
 287         int ssndChunkSize       = -1;
 288         //int ssndOffset                        = headerSize - 16;
 289         int ssndOffset                  = aiffFileFormat.getSsndChunkOffset();
 290         short channels = (short) format.getChannels();
 291         short sampleSize = (short) format.getSampleSizeInBits();
 292         int ssndBlockSize               = (channels * sampleSize);
 293         int numFrames                   = aiffFileFormat.getFrameLength();
 294         long dataSize            = -1;
 295         if( numFrames != AudioSystem.NOT_SPECIFIED) {
 296             dataSize = (long) numFrames * ssndBlockSize / 8;
 297             ssndChunkSize = (int)dataSize + 16;
 298             aiffLength = (int)dataSize+headerSize;
 299         }
 300         float sampleFramesPerSecond = format.getSampleRate();
 301         int compCode = AiffFileFormat.AIFC_PCM;
 302 
 303         byte header[] = null;
 304         ByteArrayInputStream headerStream = null;
 305         ByteArrayOutputStream baos = null;
 306         DataOutputStream dos = null;
 307         SequenceInputStream aiffStream = null;
 308         InputStream codedAudioStream = audioStream;
 309 
 310         // if we need to do any format conversion, do it here....
 311 
 312         if( audioStream instanceof AudioInputStream ) {
 313 
 314             streamFormat = ((AudioInputStream)audioStream).getFormat();
 315             encoding = streamFormat.getEncoding();
 316 


 386         dos.writeInt( (ssndChunkSize-8) );
 387         // ssndOffset and ssndBlockSize set to 0 upon
 388         // recommendation in "Sound Manager" chapter in
 389         // "Inside Macintosh Sound", pp 2-87  (from Babu)
 390         dos.writeInt(0);        // ssndOffset
 391         dos.writeInt(0);        // ssndBlockSize
 392 
 393         // Concat this with the audioStream and return it
 394 
 395         dos.close();
 396         header = baos.toByteArray();
 397         headerStream = new ByteArrayInputStream( header );
 398 
 399         aiffStream = new SequenceInputStream(headerStream,
 400                             new NoCloseInputStream(codedAudioStream));
 401 
 402         return aiffStream;
 403 
 404     }
 405 
 406 
 407 
 408 
 409     // HELPER METHODS
 410 
 411     private static final int DOUBLE_MANTISSA_LENGTH = 52;
 412     private static final int DOUBLE_EXPONENT_LENGTH = 11;
 413     private static final long DOUBLE_SIGN_MASK     = 0x8000000000000000L;
 414     private static final long DOUBLE_EXPONENT_MASK = 0x7FF0000000000000L;
 415     private static final long DOUBLE_MANTISSA_MASK = 0x000FFFFFFFFFFFFFL;
 416     private static final int DOUBLE_EXPONENT_OFFSET = 1023;
 417 
 418     private static final int EXTENDED_EXPONENT_OFFSET = 16383;
 419     private static final int EXTENDED_MANTISSA_LENGTH = 63;
 420     private static final int EXTENDED_EXPONENT_LENGTH = 15;
 421     private static final long EXTENDED_INTEGER_MASK = 0x8000000000000000L;
 422 
 423     /**
 424      * Extended precision IEEE floating-point conversion routine.
 425      * @argument DataOutputStream
 426      * @argument double
 427      * @exception IOException
 428      */


 435            ignored, too, as they, too, do not represent useful sample rates. */
 436         long doubleBits = Double.doubleToLongBits((double) f);
 437 
 438         long sign = (doubleBits & DOUBLE_SIGN_MASK)
 439             >> (DOUBLE_EXPONENT_LENGTH + DOUBLE_MANTISSA_LENGTH);
 440         long doubleExponent = (doubleBits & DOUBLE_EXPONENT_MASK)
 441             >> DOUBLE_MANTISSA_LENGTH;
 442         long doubleMantissa = doubleBits & DOUBLE_MANTISSA_MASK;
 443 
 444         long extendedExponent = doubleExponent - DOUBLE_EXPONENT_OFFSET
 445             + EXTENDED_EXPONENT_OFFSET;
 446         long extendedMantissa = doubleMantissa
 447             << (EXTENDED_MANTISSA_LENGTH - DOUBLE_MANTISSA_LENGTH);
 448         long extendedSign = sign << EXTENDED_EXPONENT_LENGTH;
 449         short extendedBits79To64 = (short) (extendedSign | extendedExponent);
 450         long extendedBits63To0 = EXTENDED_INTEGER_MASK | extendedMantissa;
 451 
 452         dos.writeShort(extendedBits79To64);
 453         dos.writeLong(extendedBits63To0);
 454     }
 455 
 456 
 457 }


  42 import javax.sound.sampled.AudioFormat;
  43 import javax.sound.sampled.AudioInputStream;
  44 import javax.sound.sampled.AudioSystem;
  45 
  46 //$$fb this class is buggy. Should be replaced in future.
  47 
  48 /**
  49  * AIFF file writer.
  50  *
  51  * @author Jan Borgersen
  52  */
  53 public final class AiffFileWriter extends SunFileWriter {
  54 
  55     /**
  56      * Constructs a new AiffFileWriter object.
  57      */
  58     public AiffFileWriter() {
  59         super(new AudioFileFormat.Type[]{AudioFileFormat.Type.AIFF});
  60     }
  61 

  62     // METHODS TO IMPLEMENT AudioFileWriter
  63 
  64     @Override
  65     public AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream) {
  66 
  67         AudioFileFormat.Type[] filetypes = new AudioFileFormat.Type[types.length];
  68         System.arraycopy(types, 0, filetypes, 0, types.length);
  69 
  70         // make sure we can write this stream
  71         AudioFormat format = stream.getFormat();
  72         AudioFormat.Encoding encoding = format.getEncoding();
  73 
  74         if( (AudioFormat.Encoding.ALAW.equals(encoding)) ||
  75             (AudioFormat.Encoding.ULAW.equals(encoding)) ||
  76             (AudioFormat.Encoding.PCM_SIGNED.equals(encoding)) ||
  77             (AudioFormat.Encoding.PCM_UNSIGNED.equals(encoding)) ) {
  78 
  79             return filetypes;
  80         }
  81 
  82         return new AudioFileFormat.Type[0];
  83     }
  84 

  85     @Override
  86     public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException {
  87         Objects.requireNonNull(stream);
  88         Objects.requireNonNull(fileType);
  89         Objects.requireNonNull(out);
  90 
  91         //$$fb the following check must come first ! Otherwise
  92         // the next frame length check may throw an IOException and
  93         // interrupt iterating File Writers. (see bug 4351296)
  94 
  95         // throws IllegalArgumentException if not supported
  96         AiffFileFormat aiffFileFormat = (AiffFileFormat)getAudioFileFormat(fileType, stream);
  97 
  98         // we must know the total data length to calculate the file length
  99         if( stream.getFrameLength() == AudioSystem.NOT_SPECIFIED ) {
 100             throw new IOException("stream length not specified");
 101         }
 102 
 103         return writeAiffFile(stream, aiffFileFormat, out);

 104     }
 105 

 106     @Override
 107     public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException {
 108         Objects.requireNonNull(stream);
 109         Objects.requireNonNull(fileType);
 110         Objects.requireNonNull(out);
 111 
 112         // throws IllegalArgumentException if not supported
 113         AiffFileFormat aiffFileFormat = (AiffFileFormat)getAudioFileFormat(fileType, stream);
 114 
 115         // first write the file without worrying about length fields
 116         FileOutputStream fos = new FileOutputStream( out );     // throws IOException
 117         BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize );
 118         int bytesWritten = writeAiffFile(stream, aiffFileFormat, bos );
 119         bos.close();
 120 
 121         // now, if length fields were not specified, calculate them,
 122         // open as a random access file, write the appropriate fields,
 123         // close again....
 124         if( aiffFileFormat.getByteLength()== AudioSystem.NOT_SPECIFIED ) {
 125 
 126             // $$kk: 10.22.99: jan: please either implement this or throw an exception!
 127             // $$fb: 2001-07-13: done. Fixes Bug 4479981
 128             int channels = aiffFileFormat.getFormat().getChannels();
 129             int sampleSize = aiffFileFormat.getFormat().getSampleSizeInBits();
 130             int ssndBlockSize = channels * ((sampleSize + 7) / 8);
 131 
 132             int aiffLength=bytesWritten;
 133             int ssndChunkSize=aiffLength-aiffFileFormat.getHeaderSize()+16;
 134             long dataSize=ssndChunkSize-16;
 135             //TODO possibly incorrect round
 136             int numFrames = (int) (dataSize / ssndBlockSize);
 137 
 138             RandomAccessFile raf=new RandomAccessFile(out, "rw");
 139             // skip FORM magic
 140             raf.skipBytes(4);
 141             raf.writeInt(aiffLength-8);
 142             // skip aiff2 magic, fver chunk, comm magic, comm size, channel count,
 143             raf.skipBytes(4+aiffFileFormat.getFverChunkSize()+4+4+2);
 144             // write frame count
 145             raf.writeInt(numFrames);
 146             // skip sample size, samplerate, SSND magic
 147             raf.skipBytes(2+10+4);
 148             raf.writeInt(ssndChunkSize-8);
 149             // that's all
 150             raf.close();
 151         }
 152 
 153         return bytesWritten;
 154     }
 155 
 156 
 157     // -----------------------------------------------------------------------
 158 
 159     /**
 160      * Returns the AudioFileFormat describing the file that will be written from this AudioInputStream.
 161      * Throws IllegalArgumentException if not supported.
 162      */
 163     private AudioFileFormat getAudioFileFormat(AudioFileFormat.Type type, AudioInputStream stream) {
 164         if (!isFileTypeSupported(type, stream)) {
 165             throw new IllegalArgumentException("File type " + type + " not supported.");
 166         }
 167 
 168         AudioFormat format = null;
 169         AiffFileFormat fileFormat = null;
 170         AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
 171 
 172         AudioFormat streamFormat = stream.getFormat();
 173         AudioFormat.Encoding streamEncoding = streamFormat.getEncoding();
 174 


 175         int sampleSizeInBits;



 176         int fileSize;
 177         boolean convert8to16 = false;
 178 
 179         if( (AudioFormat.Encoding.ALAW.equals(streamEncoding)) ||
 180             (AudioFormat.Encoding.ULAW.equals(streamEncoding)) ) {
 181 
 182             if( streamFormat.getSampleSizeInBits()==8 ) {
 183 
 184                 encoding = AudioFormat.Encoding.PCM_SIGNED;
 185                 sampleSizeInBits=16;
 186                 convert8to16 = true;
 187 
 188             } else {
 189 
 190                 // can't convert non-8-bit ALAW,ULAW
 191                 throw new IllegalArgumentException("Encoding " + streamEncoding + " supported only for 8-bit data.");
 192             }
 193         } else if ( streamFormat.getSampleSizeInBits()==8 ) {
 194 
 195             encoding = AudioFormat.Encoding.PCM_UNSIGNED;


 212 
 213 
 214         if( stream.getFrameLength()!=AudioSystem.NOT_SPECIFIED ) {
 215             if( convert8to16 ) {
 216                 fileSize = (int)stream.getFrameLength()*streamFormat.getFrameSize()*2 + AiffFileFormat.AIFF_HEADERSIZE;
 217             } else {
 218                 fileSize = (int)stream.getFrameLength()*streamFormat.getFrameSize() + AiffFileFormat.AIFF_HEADERSIZE;
 219             }
 220         } else {
 221             fileSize = AudioSystem.NOT_SPECIFIED;
 222         }
 223 
 224         fileFormat = new AiffFileFormat( AudioFileFormat.Type.AIFF,
 225                                          fileSize,
 226                                          format,
 227                                          (int)stream.getFrameLength() );
 228 
 229         return fileFormat;
 230     }
 231 

 232     private int writeAiffFile(InputStream in, AiffFileFormat aiffFileFormat, OutputStream out) throws IOException {
 233 
 234         int bytesRead = 0;
 235         int bytesWritten = 0;
 236         InputStream fileStream = getFileStream(aiffFileFormat, in);
 237         byte buffer[] = new byte[bisBufferSize];
 238         int maxLength = aiffFileFormat.getByteLength();
 239 
 240         while( (bytesRead = fileStream.read( buffer )) >= 0 ) {
 241             if (maxLength>0) {
 242                 if( bytesRead < maxLength ) {
 243                     out.write( buffer, 0, bytesRead );
 244                     bytesWritten += bytesRead;
 245                     maxLength -= bytesRead;
 246                 } else {
 247                     out.write( buffer, 0, maxLength );
 248                     bytesWritten += maxLength;
 249                     maxLength = 0;
 250                     break;
 251                 }
 252 
 253             } else {
 254                 out.write( buffer, 0, bytesRead );
 255                 bytesWritten += bytesRead;
 256             }
 257         }
 258 
 259         return bytesWritten;
 260     }
 261 
 262     private InputStream getFileStream(AiffFileFormat aiffFileFormat, InputStream audioStream) throws IOException  {
 263 
 264         // private method ... assumes aiffFileFormat is a supported file format
 265 
 266         AudioFormat format = aiffFileFormat.getFormat();
 267         AudioFormat streamFormat = null;
 268         AudioFormat.Encoding encoding = null;
 269 
 270         //$$fb a little bit nicer handling of constants


 271         int headerSize          = aiffFileFormat.getHeaderSize();

 272         //int fverChunkSize       = 0;
 273         int fverChunkSize       = aiffFileFormat.getFverChunkSize();

 274         int commChunkSize       = aiffFileFormat.getCommChunkSize();
 275         int aiffLength          = -1;
 276         int ssndChunkSize       = -1;

 277         int ssndOffset                  = aiffFileFormat.getSsndChunkOffset();
 278         short channels = (short) format.getChannels();
 279         short sampleSize = (short) format.getSampleSizeInBits();
 280         int ssndBlockSize = channels * ((sampleSize + 7) / 8);
 281         int numFrames = aiffFileFormat.getFrameLength();
 282         long dataSize = -1;
 283         if( numFrames != AudioSystem.NOT_SPECIFIED) {
 284             dataSize = (long) numFrames * ssndBlockSize;
 285             ssndChunkSize = (int)dataSize + 16;
 286             aiffLength = (int)dataSize+headerSize;
 287         }
 288         float sampleFramesPerSecond = format.getSampleRate();
 289         int compCode = AiffFileFormat.AIFC_PCM;
 290 
 291         byte header[] = null;
 292         ByteArrayInputStream headerStream = null;
 293         ByteArrayOutputStream baos = null;
 294         DataOutputStream dos = null;
 295         SequenceInputStream aiffStream = null;
 296         InputStream codedAudioStream = audioStream;
 297 
 298         // if we need to do any format conversion, do it here....
 299 
 300         if( audioStream instanceof AudioInputStream ) {
 301 
 302             streamFormat = ((AudioInputStream)audioStream).getFormat();
 303             encoding = streamFormat.getEncoding();
 304 


 374         dos.writeInt( (ssndChunkSize-8) );
 375         // ssndOffset and ssndBlockSize set to 0 upon
 376         // recommendation in "Sound Manager" chapter in
 377         // "Inside Macintosh Sound", pp 2-87  (from Babu)
 378         dos.writeInt(0);        // ssndOffset
 379         dos.writeInt(0);        // ssndBlockSize
 380 
 381         // Concat this with the audioStream and return it
 382 
 383         dos.close();
 384         header = baos.toByteArray();
 385         headerStream = new ByteArrayInputStream( header );
 386 
 387         aiffStream = new SequenceInputStream(headerStream,
 388                             new NoCloseInputStream(codedAudioStream));
 389 
 390         return aiffStream;
 391 
 392     }
 393 



 394     // HELPER METHODS
 395 
 396     private static final int DOUBLE_MANTISSA_LENGTH = 52;
 397     private static final int DOUBLE_EXPONENT_LENGTH = 11;
 398     private static final long DOUBLE_SIGN_MASK     = 0x8000000000000000L;
 399     private static final long DOUBLE_EXPONENT_MASK = 0x7FF0000000000000L;
 400     private static final long DOUBLE_MANTISSA_MASK = 0x000FFFFFFFFFFFFFL;
 401     private static final int DOUBLE_EXPONENT_OFFSET = 1023;
 402 
 403     private static final int EXTENDED_EXPONENT_OFFSET = 16383;
 404     private static final int EXTENDED_MANTISSA_LENGTH = 63;
 405     private static final int EXTENDED_EXPONENT_LENGTH = 15;
 406     private static final long EXTENDED_INTEGER_MASK = 0x8000000000000000L;
 407 
 408     /**
 409      * Extended precision IEEE floating-point conversion routine.
 410      * @argument DataOutputStream
 411      * @argument double
 412      * @exception IOException
 413      */


 420            ignored, too, as they, too, do not represent useful sample rates. */
 421         long doubleBits = Double.doubleToLongBits((double) f);
 422 
 423         long sign = (doubleBits & DOUBLE_SIGN_MASK)
 424             >> (DOUBLE_EXPONENT_LENGTH + DOUBLE_MANTISSA_LENGTH);
 425         long doubleExponent = (doubleBits & DOUBLE_EXPONENT_MASK)
 426             >> DOUBLE_MANTISSA_LENGTH;
 427         long doubleMantissa = doubleBits & DOUBLE_MANTISSA_MASK;
 428 
 429         long extendedExponent = doubleExponent - DOUBLE_EXPONENT_OFFSET
 430             + EXTENDED_EXPONENT_OFFSET;
 431         long extendedMantissa = doubleMantissa
 432             << (EXTENDED_MANTISSA_LENGTH - DOUBLE_MANTISSA_LENGTH);
 433         long extendedSign = sign << EXTENDED_EXPONENT_LENGTH;
 434         short extendedBits79To64 = (short) (extendedSign | extendedExponent);
 435         long extendedBits63To0 = EXTENDED_INTEGER_MASK | extendedMantissa;
 436 
 437         dos.writeShort(extendedBits79To64);
 438         dos.writeLong(extendedBits63To0);
 439     }


 440 }
< prev index next >