Coverage Report - org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataStreamInfo
 
Classes in this File Line Coverage Branch Coverage Complexity
MetadataBlockDataStreamInfo
95%
37/39
50%
1/2
1.154
 
 1  
 /*
 2  
  * Entagged Audio Tag library
 3  
  * Copyright (c) 2003-2005 Rapha�l Slinckx <raphael@slinckx.net>
 4  
  * 
 5  
  * This library is free software; you can redistribute it and/or
 6  
  * modify it under the terms of the GNU Lesser General Public
 7  
  * License as published by the Free Software Foundation; either
 8  
  * version 2.1 of the License, or (at your option) any later version.
 9  
  *  
 10  
  * This library is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
  * Lesser General Public License for more details.
 14  
  * 
 15  
  * You should have received a copy of the GNU Lesser General Public
 16  
  * License along with this library; if not, write to the Free Software
 17  
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 18  
  */
 19  
 package org.jaudiotagger.audio.flac.metadatablock;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.io.RandomAccessFile;
 23  
 import java.nio.ByteBuffer;
 24  
 import java.util.logging.Logger;
 25  
 
 26  
 /**
 27  
  * Stream Info
 28  
  * <p/>
 29  
  * <p>This block has information about the whole stream, like sample rate, number of channels, total number of samples,
 30  
  * etc. It must be present as the first metadata block in the stream. Other metadata blocks may follow, and ones
 31  
  * that the decoder doesn't understand, it will skip.
 32  
  * Format:
 33  
  * <Size in bits> Info
 34  
  * <16> The minimum block size (in samples) used in the stream.
 35  
  * <16> The maximum block size (in samples) used in the stream. (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream.
 36  
  * <24> The minimum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
 37  
  * <24> The maximum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
 38  
  * <20> Sample rate in Hz. Though 20 bits are available, the maximum sample rate is limited by the structure of frame headers to 655350Hz. Also,
 39  
  * a value of 0 is invalid.
 40  
  * <3>         (number of channels)-1. FLAC supports from 1 to 8 channels
 41  
  * <5>         (bits per sample)-1. FLAC supports from 4 to 32 bits per sample. Currently the reference encoder and decoders only support up to 24 bits per sample.
 42  
  * <36>         Total samples in stream. 'Samples' means inter-channel sample,
 43  
  * i.e. one second of 44.1Khz audio will have 44100 samples regardless of the number of channels.
 44  
  * A value of zero here means the number of total samples is unknown.
 45  
  * <128>         MD5 signature of the unencoded audio data. This allows the decoder to determine if an error exists in the audio data
 46  
  * even when the error does not result in an invalid bitstream.
 47  
  * NOTES
 48  
  * * FLAC specifies a minimum block size of 16 and a maximum block size of 65535, meaning the bit patterns corresponding to the numbers 0-15 in the minimum blocksize and maximum blocksize fields are invalid.
 49  
  */
 50  
 public class MetadataBlockDataStreamInfo
 51  
 {
 52  
     public static final int STREAM_INFO_DATA_LENGTH = 34;
 53  
 
 54  
     // Logger Object
 55  5
     public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac.MetadataBlockDataStreamInfo");
 56  
 
 57  
     private int minBlockSize, maxBlockSize, minFrameSize, maxFrameSize, samplingRate, samplingRatePerChannel, bitsPerSample, channelNumber, totalNumberOfSamples;
 58  
     private float length;
 59  23
     private boolean isValid = true;
 60  
 
 61  
     public MetadataBlockDataStreamInfo(MetadataBlockHeader header, RandomAccessFile raf) throws IOException
 62  23
     {
 63  23
         ByteBuffer rawdata = ByteBuffer.allocate(header.getDataLength());
 64  23
         int bytesRead = raf.getChannel().read(rawdata);
 65  23
         if (bytesRead < header.getDataLength())
 66  
         {
 67  0
             throw new IOException("Unable to read required number of databytes read:" + bytesRead + ":required:" + header.getDataLength());
 68  
         }
 69  23
         rawdata.rewind();
 70  
 
 71  23
         minBlockSize = rawdata.getShort();
 72  23
         maxBlockSize = rawdata.getShort();
 73  23
         minFrameSize = readThreeByteInteger(rawdata.get(), rawdata.get(), rawdata.get());
 74  23
         maxFrameSize = readThreeByteInteger(rawdata.get(), rawdata.get(), rawdata.get());
 75  
 
 76  23
         samplingRate = readSamplingRate(rawdata.get(), rawdata.get(), rawdata.get());
 77  23
         channelNumber = ((u(rawdata.get(12)) & 0x0E) >>> 1) + 1;
 78  23
         samplingRatePerChannel = samplingRate / channelNumber;
 79  23
         bitsPerSample = ((u(rawdata.get(12)) & 0x01) << 4) + ((u(rawdata.get(13)) & 0xF0) >>> 4) + 1;
 80  
 
 81  23
         totalNumberOfSamples = readTotalNumberOfSamples(rawdata.get(13), rawdata.get(14), rawdata.get(15), rawdata.get(16), rawdata.get(17));
 82  
 
 83  23
         length = (float) ((double) totalNumberOfSamples / samplingRate);
 84  23
         logger.info(this.toString());
 85  23
     }
 86  
 
 87  
     public String toString()
 88  
     {
 89  
 
 90  23
         return "MinBlockSize:" + minBlockSize + "MaxBlockSize:" + maxBlockSize + "MinFrameSize:" + minFrameSize + "MaxFrameSize:" + maxFrameSize + "SampleRateTotal:" + samplingRate + "SampleRatePerChannel:" + samplingRatePerChannel + ":Channel number:" + channelNumber + ":Bits per sample: " + bitsPerSample + ":TotalNumberOfSamples: " + totalNumberOfSamples + ":Length: " + length;
 91  
 
 92  
     }
 93  
 
 94  
     public int getLength()
 95  
     {
 96  23
         return (int) length;
 97  
     }
 98  
 
 99  
     public float getPreciseLength()
 100  
     {
 101  46
         return length;
 102  
     }
 103  
 
 104  
     public int getChannelNumber()
 105  
     {
 106  23
         return channelNumber;
 107  
     }
 108  
 
 109  
     public int getSamplingRate()
 110  
     {
 111  23
         return samplingRate;
 112  
     }
 113  
 
 114  
     public int getSamplingRatePerChannel()
 115  
     {
 116  0
         return samplingRatePerChannel;
 117  
     }
 118  
 
 119  
     public String getEncodingType()
 120  
     {
 121  23
         return "FLAC " + bitsPerSample + " bits";
 122  
     }
 123  
 
 124  
     public boolean isValid()
 125  
     {
 126  23
         return isValid;
 127  
     }
 128  
 
 129  
     private int readThreeByteInteger(byte b1, byte b2, byte b3)
 130  
     {
 131  46
         int rate = (u(b1) << 16) + (u(b2) << 8) + (u(b3));
 132  46
         return rate;
 133  
     }
 134  
 
 135  
     //TODO this code seems to be give a sampling rate over 21 bytes instead of 20 bytes but attempt to change
 136  
     //to 21 bytes give wrong value
 137  
     private int readSamplingRate(byte b1, byte b2, byte b3)
 138  
     {
 139  23
         int rate = (u(b1) << 12) + (u(b2) << 4) + ((u(b3) & 0xF0) >>> 4);
 140  23
         return rate;
 141  
 
 142  
     }
 143  
 
 144  
     private int readTotalNumberOfSamples(byte b1, byte b2, byte b3, byte b4, byte b5)
 145  
     {
 146  23
         int nb = u(b5);
 147  23
         nb += u(b4) << 8;
 148  23
         nb += u(b3) << 16;
 149  23
         nb += u(b2) << 24;
 150  23
         nb += (u(b1) & 0x0F) << 32;
 151  23
         return nb;
 152  
     }
 153  
 
 154  
     private int u(int i)
 155  
     {
 156  391
         return i & 0xFF;
 157  
     }
 158  
 }