/* * Entagged Audio Tag library * Copyright (c) 2004-2005 Christian Laireiter <liree@web.de> * * 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.asf.data; import org.jaudiotagger.audio.asf.util.Utils; import java.math.BigInteger; /** * This class represents the stream chunk describing an audio stream. <br> * * @author Christian Laireiter */ public final class AudioStreamChunk extends StreamChunk { /** * Stores the hex values of codec identifiers to their descriptions. <br> */ public final static String[][] CODEC_DESCRIPTIONS = { { "161", " (Windows Media Audio (ver 7,8,9))" }, { "162", " (Windows Media Audio 9 series (Professional))" }, { "163", "(Windows Media Audio 9 series (Lossless))" }, { "7A21", " (GSM-AMR (CBR))" }, { "7A22", " (GSM-AMR (VBR))" } }; /** * Stores the audio codec number for WMA */ public final static long WMA = 0x161; /** * Stores the audio codec number for WMA (CBR) */ public final static long WMA_CBR = 0x7A21; /** * Stores the audio codec number for WMA_LOSSLESS */ public final static long WMA_LOSSLESS = 0x163; /** * Stores the audio codec number for WMA_PRO */ public final static long WMA_PRO = 0x162; /** * Stores the audio codec number for WMA (VBR) */ public final static long WMA_VBR = 0x7A22; /** * Stores the average amount of bytes used by audio stream. <br> * This value is a field within type specific data of audio stream. Maybe it * could be used to calculate the KBPs. */ private long averageBytesPerSec; /** * Amount of bits used per sample. <br> */ private int bitsPerSample; /** * The block alignment of the audio data. */ private long blockAlignment; /** * Number of channels. */ private long channelCount; /** * Some data which needs to be interpreted if the codec is handled. */ private byte[] codecData = new byte[0]; /** * The audio compression format code. */ private long compressionFormat; /** * this field stores the error concealment type. */ private GUID errorConcealment; /** * Sampling rate of audio stream. */ private long samplingRate; /** * Creates an instance. * * @param chunkLen * Length of the entire chunk (including guid and size) */ public AudioStreamChunk(final BigInteger chunkLen) { super(GUID.GUID_AUDIOSTREAM, chunkLen); } /** * @return Returns the averageBytesPerSec. */ public long getAverageBytesPerSec() { return this.averageBytesPerSec; } /** * @return Returns the bitsPerSample. */ public int getBitsPerSample() { return this.bitsPerSample; } /** * @return Returns the blockAlignment. */ public long getBlockAlignment() { return this.blockAlignment; } /** * @return Returns the channelCount. */ public long getChannelCount() { return this.channelCount; } /** * @return Returns the codecData. */ public byte[] getCodecData() { return this.codecData.clone(); } /** * This method will take a look at {@link #compressionFormat}and returns a * String with its hex value and if known a textual note on what coded it * represents. <br> * * @return A description for the used codec. */ public String getCodecDescription() { final StringBuilder result = new StringBuilder(Long .toHexString(getCompressionFormat())); String furtherDesc = " (Unknown)"; for (final String[] aCODEC_DESCRIPTIONS : CODEC_DESCRIPTIONS) { if (aCODEC_DESCRIPTIONS[0].equalsIgnoreCase(result.toString())) { furtherDesc = aCODEC_DESCRIPTIONS[1]; break; } } if (result.length() % 2 == 0) { result.insert(0, "0x"); } else { result.insert(0, "0x0"); } result.append(furtherDesc); return result.toString(); } /** * @return Returns the compressionFormat. */ public long getCompressionFormat() { return this.compressionFormat; } /** * @return Returns the errorConcealment. */ public GUID getErrorConcealment() { return this.errorConcealment; } /** * This method takes the value of {@link #getAverageBytesPerSec()}and * calculates the kbps out of it, by simply multiplying by 8 and dividing by * 1000. <br> * * @return amount of bits per second in kilo bits. */ public int getKbps() { return (int) getAverageBytesPerSec() * 8 / 1000; } /** * @return Returns the samplingRate. */ public long getSamplingRate() { return this.samplingRate; } /** * This mehtod returns whether the audio stream data is error concealed. <br> * For now only interleaved concealment is known. <br> * * @return <code>true</code> if error concealment is used. */ public boolean isErrorConcealed() { return getErrorConcealment().equals( GUID.GUID_AUDIO_ERROR_CONCEALEMENT_INTERLEAVED); } /** * * {@inheritDoc} */ @Override public String prettyPrint(final String prefix) { final StringBuilder result = new StringBuilder(super.prettyPrint(prefix)); result.append(prefix).append(" |-> Audio info:").append( Utils.LINE_SEPARATOR); result.append(prefix).append(" | : Bitrate : ").append(getKbps()) .append(Utils.LINE_SEPARATOR); result.append(prefix).append(" | : Channels : ").append( getChannelCount()).append(" at ").append(getSamplingRate()) .append(" Hz").append(Utils.LINE_SEPARATOR); result.append(prefix).append(" | : Bits per Sample: ").append( getBitsPerSample()).append(Utils.LINE_SEPARATOR); result.append(prefix).append(" | : Formatcode: ").append( getCodecDescription()).append(Utils.LINE_SEPARATOR); return result.toString(); } /** * @param avgeBytesPerSec * The averageBytesPerSec to set. */ public void setAverageBytesPerSec(final long avgeBytesPerSec) { this.averageBytesPerSec = avgeBytesPerSec; } /** * Sets the bitsPerSample * * @param bps */ public void setBitsPerSample(final int bps) { this.bitsPerSample = bps; } /** * Sets the blockAlignment. * * @param align */ public void setBlockAlignment(final long align) { this.blockAlignment = align; } /** * @param channels * The channelCount to set. */ public void setChannelCount(final long channels) { this.channelCount = channels; } /** * Sets the codecData * * @param codecSpecificData */ public void setCodecData(final byte[] codecSpecificData) { if (codecSpecificData == null) { throw new IllegalArgumentException(); } this.codecData = codecSpecificData.clone(); } /** * @param cFormatCode * The compressionFormat to set. */ public void setCompressionFormat(final long cFormatCode) { this.compressionFormat = cFormatCode; } /** * This method sets the error concealment type which is given by two GUIDs. <br> * * @param errConc * the type of error concealment the audio stream is stored as. */ public void setErrorConcealment(final GUID errConc) { this.errorConcealment = errConc; } /** * @param sampRate * The samplingRate to set. */ public void setSamplingRate(final long sampRate) { this.samplingRate = sampRate; } }