/* * @(#)AudioFormat.java - parse Audioheaders, basic class * * Copyright (c) 2003-2008 by dvb.matt, All Rights Reserved. * * This file is part of ProjectX, a free Java based demux utility. * By the authors, ProjectX is intended for educational purposes only, * as a non-commercial test project. * * The part of audio parsing was derived from the MPEG/Audio * Software Simulation Group's audio codec and ATSC A/52 in a special modified manner. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package net.sourceforge.dvb.projectx.audio; import java.io.RandomAccessFile; import java.io.IOException; import net.sourceforge.dvb.projectx.parser.CommonParsing; import net.sourceforge.dvb.projectx.common.Common; public class AudioFormat extends Object { private AudioFormat impl = null; /** * */ public AudioFormat(int type) { setNewType(type); } /** * */ public AudioFormat(byte[] frame) { //unused, meant for autodetection } /** * */ public AudioFormat() { init(); } /** * */ public void setNewType(int type) { switch (type) { case CommonParsing.DTS_AUDIO: impl = new AudioFormatDTS(); break; case CommonParsing.AC3_AUDIO: impl = new AudioFormatAC3(); break; case CommonParsing.LPCM_AUDIO: impl = new AudioFormatLPCM(); break; case CommonParsing.WAV_AUDIO: impl = new AudioFormatWAV(); break; case CommonParsing.MPEG_AUDIO: impl = new AudioFormatMPA(); break; case CommonParsing.AAC_AUDIO: impl = new AudioFormatAAC();// break; } } private boolean INTEL; private int ID; private int Layer; private int Protection_bit; private int Private_bit; private int Bitrate; private int Sampling_frequency; private int Padding_bit; private int Mode; private int Mode_extension; private int Copyright; private int Original; private int Channel; private int Emphasis; private int Size; private int Size_base; private double Time_length; private int nID; private int nLayer; private int nProtection_bit; private int nPrivate_bit; private int nBitrate; private int nSampling_frequency; private int nPadding_bit; private int nMode; private int nMode_extension; private int nCopyright; private int nOriginal; private int nChannel; private int nEmphasis; private int nSize; private int nSize_base; private double nTime_length; private int lID; private int lLayer; private int lProtection_bit; private int lPrivate_bit; private int lBitrate; private int lSampling_frequency; private int lPadding_bit; private int lMode; private int lMode_extension; private int lCopyright; private int lOriginal; private int lChannel; private int lEmphasis; private int lSize; private int lSize_base; private double lTime_length; /** * */ public void init() { setINTEL(false); setID(0); setLayer(0); setProtectionBit(0); setPrivateBit(0); setBitrate(0); setSamplingFrequency(0); setPaddingBit(0); setPrivateBit(0); setMode(0); setModeExtension(0); setCopyright(0); setOriginal(0); setChannel(0); setEmphasis(0); setSize(0); setSizeBase(0); setFrameTimeLength(0.0); } /** * */ public boolean isINTEL() { return (impl == null ? INTEL : impl.isINTEL()); } /** * */ public void setINTEL(boolean b) { if (impl != null) impl.setINTEL(b); INTEL = b; } /** * */ public int getID() { return (impl == null ? ID : impl.getID()); } /** * */ public void setID(int val) { if (impl != null) impl.setID(val); ID = val; } /** * */ public int getLayer() { return (impl == null ? Layer : impl.getLayer()); } /** * */ public void setLayer(int val) { if (impl != null) impl.setLayer(val); Layer = val; } /** * */ public int getBitrate() { return (impl == null ? Bitrate : impl.getBitrate()); } /** * */ public void setBitrate(int val) { if (impl != null) impl.setBitrate(val); Bitrate = val; } /** * */ public int getSamplingFrequency() { return (impl == null ? Sampling_frequency : impl.getSamplingFrequency()); } /** * */ public void setSamplingFrequency(int val) { if (impl != null) impl.setSamplingFrequency(val); Sampling_frequency = val; } /** * */ public int getMode() { return (impl == null ? Mode : impl.getMode()); } /** * */ public void setMode(int val) { if (impl != null) impl.setMode(val); Mode = val; } /** * */ public int getModeExtension() { return (impl == null ? Mode_extension : impl.getModeExtension()); } /** * */ public void setModeExtension(int val) { if (impl != null) impl.setModeExtension(val); Mode_extension = val; } /** * */ public int getEmphasis() { return (impl == null ? Emphasis : impl.getEmphasis()); } /** * */ public void setEmphasis(int val) { if (impl != null) impl.setEmphasis(val); Emphasis = val; } /** * */ public int getSize() { return (impl == null ? Size : impl.getSize()); } /** * */ public void setSize(int val) { if (impl != null) impl.setSize(val); Size = val; } /** * */ public int getSizeBase() { return (impl == null ? Size_base : impl.getSizeBase()); } /** * */ public void setSizeBase(int val) { if (impl != null) impl.setSizeBase(val); //slackalan 250312 //setSizeBase(val); Size_base = val; } /** * */ public int getChannel() { return (impl == null ? Channel : impl.getChannel()); } /** * */ public void setChannel(int val) { if (impl != null) impl.setChannel(val); Channel = val; } /** * */ public int getPaddingBit() { return (impl == null ? Padding_bit : impl.getPaddingBit()); } /** * */ public void setPaddingBit(int val) { if (impl != null) impl.setPaddingBit(val); Padding_bit = val; } /** * */ public int getPrivateBit() { return (impl == null ? Private_bit : impl.getPrivateBit()); } /** * */ public void setPrivateBit(int val) { if (impl != null) impl.setPrivateBit(val); Private_bit = val; } /** * */ public int getOriginal() { return (impl == null ? Original : impl.getOriginal()); } /** * */ public void setOriginal(int val) { if (impl != null) impl.setOriginal(val); Original = val; } /** * */ public int getCopyright() { return (impl == null ? Copyright : impl.getCopyright()); } /** * */ public void setCopyright(int val) { if (impl != null) impl.setCopyright(val); Copyright = val; } /** * */ public int getProtectionBit() { return (impl == null ? Protection_bit : impl.getProtectionBit()); } /** * */ public void setProtectionBit(int val) { if (impl != null) impl.setProtectionBit(val); Protection_bit = val; } /** * */ public double getFrameTimeLength() { return (impl == null ? Time_length : impl.getFrameTimeLength()); } /** * */ public void setFrameTimeLength(double val) { if (impl != null) impl.setFrameTimeLength(val); Time_length = val; } /////// /** * */ public int getLastID() { return (impl == null ? lID : impl.getLastID()); } /** * */ public void setLastID(int val) { if (impl != null) impl.setLastID(val); lID = val; } /** * */ public int getLastLayer() { return (impl == null ? lLayer : impl.getLastLayer()); } /** * */ public void setLastLayer(int val) { if (impl != null) impl.setLastLayer(val); lLayer = val; } /** * */ public int getLastBitrate() { return (impl == null ? lBitrate : impl.getLastBitrate()); } /** * */ public void setLastBitrate(int val) { if (impl != null) impl.setLastBitrate(val); lBitrate = val; } /** * */ public int getLastSamplingFrequency() { return (impl == null ? lSampling_frequency : impl.getLastSamplingFrequency()); } /** * */ public void setLastSamplingFrequency(int val) { if (impl != null) impl.setLastSamplingFrequency(val); lSampling_frequency = val; } /** * */ public int getLastMode() { return (impl == null ? lMode : impl.getLastMode()); } /** * */ public void setLastMode(int val) { if (impl != null) impl.setLastMode(val); lMode = val; } /** * */ public int getLastModeExtension() { return (impl == null ? lMode_extension : impl.getLastModeExtension()); } /** * */ public void setLastModeExtension(int val) { if (impl != null) impl.setLastModeExtension(val); lMode_extension = val; } /** * */ public int getLastEmphasis() { return (impl == null ? lEmphasis : impl.getLastEmphasis()); } /** * */ public void setLastEmphasis(int val) { if (impl != null) impl.setLastEmphasis(val); lEmphasis = val; } /** * */ public int getLastSize() { return (impl == null ? lSize : impl.getLastSize()); } /** * */ public void setLastSize(int val) { if (impl != null) impl.setLastSize(val); lSize = val; } /** * */ public int getLastSizeBase() { return (impl == null ? lSize_base : impl.getLastSizeBase()); } /** * */ public void setLastSizeBase(int val) { if (impl != null) impl.setLastSizeBase(val); lSize_base = val; } /** * */ public int getLastChannel() { return (impl == null ? lChannel : impl.getLastChannel()); } /** * */ public void setLastChannel(int val) { if (impl != null) impl.setLastChannel(val); lChannel = val; } /** * */ public int getLastPaddingBit() { return (impl == null ? lPadding_bit : impl.getLastPaddingBit()); } /** * */ public void setLastPaddingBit(int val) { if (impl != null) impl.setLastPaddingBit(val); lPadding_bit = val; } /** * */ public int getLastPrivateBit() { return (impl == null ? lPrivate_bit : impl.getLastPrivateBit()); } /** * */ public void setLastPrivateBit(int val) { if (impl != null) impl.setLastPrivateBit(val); lPrivate_bit = val; } /** * */ public int getLastOriginal() { return (impl == null ? lOriginal : impl.getLastOriginal()); } /** * */ public void setLastOriginal(int val) { if (impl != null) impl.setLastOriginal(val); lOriginal = val; } /** * */ public int getLastCopyright() { return (impl == null ? lCopyright : impl.getLastCopyright()); } /** * */ public void setLastCopyright(int val) { if (impl != null) impl.setLastCopyright(val); lCopyright = val; } /** * */ public int getLastProtectionBit() { return (impl == null ? lProtection_bit : impl.getLastProtectionBit()); } /** * */ public void setLastProtectionBit(int val) { if (impl != null) impl.setLastProtectionBit(val); lProtection_bit = val; } /** * */ public double getLastFrameTimeLength() { return (impl == null ? lTime_length : impl.getLastFrameTimeLength()); } /** * */ public void setLastFrameTimeLength(double val) { if (impl != null) impl.setLastFrameTimeLength(val); lTime_length = val; } /////// /** * */ public int getNextID() { return (impl == null ? nID : impl.getNextID()); } /** * */ public void setNextID(int val) { if (impl != null) impl.setNextID(val); nID = val; } /** * */ public int getNextLayer() { return (impl == null ? nLayer : impl.getNextLayer()); } /** * */ public void setNextLayer(int val) { if (impl != null) impl.setNextLayer(val); nLayer = val; } /** * */ public int getNextBitrate() { return (impl == null ? nBitrate : impl.getNextBitrate()); } /** * */ public void setNextBitrate(int val) { if (impl != null) impl.setNextBitrate(val); nBitrate = val; } /** * */ public int getNextSamplingFrequency() { return (impl == null ? nSampling_frequency : impl.getNextSamplingFrequency()); } /** * */ public void setNextSamplingFrequency(int val) { if (impl != null) impl.setNextSamplingFrequency(val); nSampling_frequency = val; } /** * */ public int getNextMode() { return (impl == null ? nMode : impl.getNextMode()); } /** * */ public void setNextMode(int val) { if (impl != null) impl.setNextMode(val); nMode = val; } /** * */ public int getNextModeExtension() { return (impl == null ? nMode_extension : impl.getNextModeExtension()); } /** * */ public void setNextModeExtension(int val) { if (impl != null) impl.setNextModeExtension(val); nMode_extension = val; } /** * */ public int getNextEmphasis() { return (impl == null ? nEmphasis : impl.getNextEmphasis()); } /** * */ public void setNextEmphasis(int val) { if (impl != null) impl.setNextEmphasis(val); nEmphasis = val; } /** * */ public int getNextSize() { return (impl == null ? nSize : impl.getNextSize()); } /** * */ public void setNextSize(int val) { if (impl != null) impl.setNextSize(val); nSize = val; } /** * */ public int getNextSizeBase() { return (impl == null ? nSize_base : impl.getNextSizeBase()); } /** * */ public void setNextSizeBase(int val) { if (impl != null) impl.setNextSizeBase(val); nSize_base = val; } /** * */ public int getNextChannel() { return (impl == null ? nChannel : impl.getNextChannel()); } /** * */ public void setNextChannel(int val) { if (impl != null) impl.setNextChannel(val); nChannel = val; } /** * */ public int getNextPaddingBit() { return (impl == null ? nPadding_bit : impl.getNextPaddingBit()); } /** * */ public void setNextPaddingBit(int val) { if (impl != null) impl.setNextPaddingBit(val); nPadding_bit = val; } /** * */ public int getNextPrivateBit() { return (impl == null ? nPrivate_bit : impl.getNextPrivateBit()); } /** * */ public void setNextPrivateBit(int val) { if (impl != null) impl.setNextPrivateBit(val); nPrivate_bit = val; } /** * */ public int getNextOriginal() { return (impl == null ? nOriginal : impl.getNextOriginal()); } /** * */ public void setNextOriginal(int val) { if (impl != null) impl.setNextOriginal(val); nOriginal = val; } /** * */ public int getNextCopyright() { return (impl == null ? nCopyright : impl.getNextCopyright()); } /** * */ public void setNextCopyright(int val) { if (impl != null) impl.setNextCopyright(val); nCopyright = val; } /** * */ public int getNextProtectionBit() { return (impl == null ? nProtection_bit : impl.getNextProtectionBit()); } /** * */ public void setNextProtectionBit(int val) { if (impl != null) impl.setNextProtectionBit(val); nProtection_bit = val; } /** * */ public double getNextFrameTimeLength() { return (impl == null ? nTime_length : impl.getNextFrameTimeLength()); } /** * */ public void setNextFrameTimeLength(double val) { if (impl != null) impl.setNextFrameTimeLength(val); nTime_length = val; } ////// /** * */ public int parseHeader(byte[] data, int offset, int endoffset) { int ret = 0; if (impl != null) { for (int i = 0; i < endoffset; i++) if ((ret = parseHeader(data, offset + i)) < 0) continue; } return ret; } /** * */ public int parseHeader(byte[] frame, int offset) { return (impl == null ? 0 : impl.parseHeader(frame, offset)); } /** * */ public int parseNextHeader(byte[] frame, int offset) { return (impl == null ? 0 : impl.parseNextHeader(frame, offset)); } /** * save last header */ public void saveHeader() { setLastID(getID()); setLastLayer(getLayer()); setLastProtectionBit(getProtectionBit()); setLastPrivateBit(getPrivateBit()); setLastBitrate(getBitrate()); setLastSamplingFrequency(getSamplingFrequency()); setLastPaddingBit(getPaddingBit()); setLastPrivateBit(getPrivateBit()); setLastMode(getMode()); setLastModeExtension(getModeExtension()); setLastCopyright(getCopyright()); setLastOriginal(getOriginal()); setLastChannel(getChannel()); setLastEmphasis(getEmphasis()); setLastSize(getSize()); setLastSizeBase(getSizeBase()); setLastFrameTimeLength(getFrameTimeLength()); } /** * */ public int compareHeader() { return (impl == null ? 0 : impl.compareHeader()); } /** * */ public String displayHeader() { return (impl == null ? "" : impl.displayHeader()); } /** * save and display last header */ public String saveAndDisplayHeader() { saveHeader(); return displayHeader(); } /** * */ public byte[] editFrame(byte[] frame, int mode) { return (impl == null ? frame : impl.editFrame(frame, mode)); } /** * */ public byte[][] convertFrame(byte[] frame, int mode) { if (impl == null) return (new byte[][]{ frame, new byte[0] }); return impl.convertFrame(frame, mode); // return (impl == null ? frame : impl.convertFrame(frame, mode)); } /** * */ public void removeCRC(byte[] frame, boolean remove) { if (impl != null) impl.removeCRC(frame, remove); } /** * */ public int validateCRC(byte[] frame, int offset, int len) { return (impl == null ? 0 : impl.validateCRC(frame, offset, len)); } /** * */ public void setAncillaryDataDecoder(boolean b1, boolean b2) { if (impl != null) impl.setAncillaryDataDecoder(b1, b2); } /** * */ public String decodeAncillaryData(byte[] frame, double frametime) { return (impl == null ? null : impl.decodeAncillaryData(frame, frametime)); } /** * */ public void parseRiffData(byte[] frame, int channel) { if (impl != null) impl.parseRiffData(frame, channel); } /** * */ public void initExtraWaveHeader(boolean bool_ACM, boolean bool_BWF, boolean bool_AC3) { if (impl != null) impl.initExtraWaveHeader(bool_ACM, bool_BWF, bool_AC3); } /** * */ public byte[] getExtraWaveHeader(int channel, boolean placeholder) { return (impl == null ? (new byte[0]) : impl.getExtraWaveHeader(channel, placeholder)); } /** * */ public void setExtraWaveData(int[] array, int channel) { if (impl != null) impl.setExtraWaveData(array, channel); } /** * */ public void setExtraWaveLength(long filelength, long timelength, int channel) { if (impl != null) impl.setExtraWaveLength(filelength, timelength, channel); } /** * returns RIFF */ public byte[] getRiffHeader() { return (new byte[] { 0x52, 0x49, 0x46, 0x46, //'RIFF' 0, 0, 0, 0, // all size LSB 0x57, 0x41, 0x56, 0x45, //'WAVE' 0x66, 0x6D, 0x74, 0x20, //'fmt ' 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x64, 0x61, 0x74, 0x61, // 'data' 0, 0, 0, 0 // data size LSB }); } /** * updates std RIFF */ public void fillStdRiffHeader(String file, long time_len) { try { RandomAccessFile riff = new RandomAccessFile(file, "rw"); int len = (int) riff.length() - 8; int bitrate = 1411200; riff.seek(4); riff.writeInt(littleEndian(len, 4, true)); //data+chunksize riff.seek(16); riff.writeInt(littleEndian(0x10, 4, true)); //chunk length riff.writeShort(littleEndian(1, 2, true)); //pcm riff.writeShort((short)littleEndian(2, 2, true)); //channels riff.writeInt(littleEndian(44100, 4, true)); //sample_freq riff.writeInt(littleEndian(bitrate / 8, 4, true)); //byterate riff.writeShort((short)littleEndian(4, 2, true)); //blockalign riff.writeShort((short)littleEndian(16, 2, true)); //bits_per_sample riff.seek(40); riff.writeInt(littleEndian(len - 36, 4, true)); //data-size riff.close(); } catch (IOException e) { Common.setExceptionMessage(e); } } /** * updates RIFF * returns playtime as int */ public long fillRiffHeader(String file) { long value = 0; try { RandomAccessFile riff = new RandomAccessFile(file, "rw"); int len = (int)riff.length() - 8; riff.seek(3); if (!isINTEL()) riff.write((byte)'X'); riff.seek(4); riff.writeInt(littleEndian(len, 4)); //data+chunksize riff.seek(16); riff.writeInt(littleEndian(0x10, 4)); //chunk length riff.writeShort(littleEndian(1, 2)); //pcm riff.writeShort((short)littleEndian(lChannel, 2)); //channels riff.writeInt(littleEndian(lSampling_frequency, 4)); //sample_freq riff.writeInt(littleEndian(lBitrate / 8, 4)); //byterate riff.writeShort((short)littleEndian(lMode, 2)); //blockalign riff.writeShort((short)littleEndian(lSize, 2)); //bits_per_sample riff.seek(40); riff.writeInt(littleEndian(len - 36, 4)); //data-size riff.close(); value = (8000L * (len - 36)) / lBitrate; } catch (IOException e) { Common.setExceptionMessage(e); } return value; } /** * */ public int littleEndian(byte[] data, int offset, int len, boolean reverse) { int value = 0; for (int a = 0; a < len; a++) value |= reverse ? ((0xFF & data[offset + a])<<(a * 8)) : ((0xFF & data[offset + a])<<((len - 1 - a) * 8)); return value; } /** * */ public int getValue(byte[] data, int offset, int len, boolean reverse) { return littleEndian(data, offset, len, reverse); } /** * */ public void setValue(byte[] array, int offset, int len, boolean bytereordering, int value) { for (int i = 0; bytereordering && i < len; i++) array[i + offset] = (byte)(0xFF & (value>>>(i * 8))); for (int i = 0, j = len - 1; !bytereordering && i < len; i++, j--) array[i + offset] = (byte)(0xFF & (value>>>(j * 8))); } /** * */ public int littleEndian(int data, int len) { return littleEndian(data, len, isINTEL()); } /** * */ public int littleEndian(int data, int len, boolean b) { if (!b) return data; if (len == 4) return ( (0xFF & data>>>24) | (0xFF & data>>>16)<<8 | (0xFF & data>>>8)<<16 | (0xFF & data)<<24 ); else return ( (0xFF & data>>>8) | (0xFF & data)<<8 ); } /** * */ public int getBits(byte buf[], int BitPos[], int N) { int Pos, Val; Pos = BitPos[0]>>>3; Val = (0xFF & buf[Pos])<<24 | (0xFF & buf[Pos+1])<<16 | (0xFF & buf[Pos+2])<<8 | (0xFF & buf[Pos+3]); Val <<= BitPos[0] & 7; Val >>>= 32-N; BitPos[0] += N; return Val; } }