/*
* Entagged Audio Tag library
* Copyright (c) 2003-2005 Raphael Slinckx <raphael@slinckx.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jaudiotagger.audio.flac;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.flac.metadatablock.BlockType;
import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataStreamInfo;
import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockHeader;
import org.jaudiotagger.audio.generic.GenericAudioHeader;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.logging.Logger;
/**
* Read info from Flac file
*/
public class FlacInfoReader {
// Logger Object
public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.flac");
private static final int NO_OF_BITS_IN_BYTE = 8;
private static final int KILOBYTES_TO_BYTES_MULTIPLIER = 1000;
public GenericAudioHeader read(RandomAccessFile raf) throws CannotReadException, IOException {
FlacStreamReader flacStream = new FlacStreamReader(raf);
flacStream.findStream();
MetadataBlockDataStreamInfo mbdsi = null;
boolean isLastBlock = false;
//Search for StreamInfo Block, but even after we found it we still have to continue through all
//the metadata blocks so that we can find the start of the audio frames which we need to calculate
//the bitrate
while (!isLastBlock) {
MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(raf);
if (mbh.getBlockType() == BlockType.STREAMINFO) {
mbdsi = new MetadataBlockDataStreamInfo(mbh, raf);
if (!mbdsi.isValid()) {
throw new CannotReadException("FLAC StreamInfo not valid");
}
} else {
raf.seek(raf.getFilePointer() + mbh.getDataLength());
}
isLastBlock = mbh.isLastBlock();
mbh = null; //Free memory
}
if (mbdsi == null) {
throw new CannotReadException("Unable to find Flac StreamInfo");
}
GenericAudioHeader info = new GenericAudioHeader();
info.setLength(mbdsi.getSongLength());
info.setPreciseLength(mbdsi.getPreciseLength());
info.setChannelNumber(mbdsi.getChannelNumber());
info.setSamplingRate(mbdsi.getSamplingRate());
info.setEncodingType(mbdsi.getEncodingType());
info.setExtraEncodingInfos("");
info.setBitrate(computeBitrate((float) mbdsi.getPreciseLength(), raf.length() - raf.getFilePointer()));
info.setTotalSamples(mbdsi.getTotalNumberOfSamples());
return info;
}
private int computeBitrate(float length, long size) {
return (int) ((size / KILOBYTES_TO_BYTES_MULTIPLIER) * NO_OF_BITS_IN_BYTE / length);
}
/**
* Count the number of metadatablocks, useful for debugging
*
* @param f
* @return
* @throws CannotReadException
* @throws IOException
*/
public int countMetaBlocks(File f) throws CannotReadException, IOException {
RandomAccessFile raf = new RandomAccessFile(f, "r");
FlacStreamReader flacStream = new FlacStreamReader(raf);
flacStream.findStream();
boolean isLastBlock = false;
int count = 0;
while (!isLastBlock) {
MetadataBlockHeader mbh = MetadataBlockHeader.readHeader(raf);
// //logger.info("Found block:" + mbh.getBlockType());
raf.seek(raf.getFilePointer() + mbh.getDataLength());
isLastBlock = mbh.isLastBlock();
mbh = null; //Free memory
count++;
}
raf.close();
return count;
}
}