package net.sourceforge.jaad.aac.syntax; import net.sourceforge.jaad.aac.AACException; import net.sourceforge.jaad.aac.SampleFrequency; /** * This class is part of JAAD ( jaadec.sourceforge.net ) that is distributed * under the Public Domain license. Code changes provided by the JCodec project * are distributed under FreeBSD license. * * @author in-somnia */ class FIL extends Element implements SyntaxConstants { public static class DynamicRangeInfo { private static final int MAX_NBR_BANDS = 7; private final boolean[] excludeMask; private final boolean[] additionalExcludedChannels; private boolean pceTagPresent; private int pceInstanceTag; private int tagReservedBits; private boolean excludedChannelsPresent; private boolean bandsPresent; private int bandsIncrement, interpolationScheme; private int[] bandTop; private boolean progRefLevelPresent; private int progRefLevel, progRefLevelReservedBits; private boolean[] dynRngSgn; private int[] dynRngCtl; public DynamicRangeInfo() { excludeMask = new boolean[MAX_NBR_BANDS]; additionalExcludedChannels = new boolean[MAX_NBR_BANDS]; } } private static final int TYPE_FILL = 0; private static final int TYPE_FILL_DATA = 1; private static final int TYPE_EXT_DATA_ELEMENT = 2; private static final int TYPE_DYNAMIC_RANGE = 11; private static final int TYPE_SBR_DATA = 13; private static final int TYPE_SBR_DATA_CRC = 14; private final boolean downSampledSBR; private DynamicRangeInfo dri; FIL(boolean downSampledSBR) { super(); this.downSampledSBR = downSampledSBR; } void decode(IBitStream _in, Element prev, SampleFrequency sf, boolean sbrEnabled, boolean smallFrames) throws AACException { int count = _in.readBits(4); if(count==15) count += _in.readBits(8)-1; count *= 8; //convert to bits final int cpy = count; final int pos = _in.getPosition(); while(count>0) { count = decodeExtensionPayload(_in, count, prev, sf, sbrEnabled, smallFrames); } final int pos2 = _in.getPosition()-pos; final int bitsLeft = cpy-pos2; if(bitsLeft>0) _in.skipBits(pos2); else if(bitsLeft<0) throw new AACException("FIL element overread: "+bitsLeft); } private int decodeExtensionPayload(IBitStream _in, int count, Element prev, SampleFrequency sf, boolean sbrEnabled, boolean smallFrames) throws AACException { final int type = _in.readBits(4); int ret = count-4; switch(type) { case TYPE_DYNAMIC_RANGE: ret = decodeDynamicRangeInfo(_in, ret); break; case TYPE_SBR_DATA: case TYPE_SBR_DATA_CRC: if(sbrEnabled) { if(prev instanceof SCE_LFE||prev instanceof CPE||prev instanceof CCE) { prev.decodeSBR(_in, sf, ret, (prev instanceof CPE), (type==TYPE_SBR_DATA_CRC), downSampledSBR, smallFrames); ret = 0; break; } else throw new AACException("SBR applied on unexpected element: "+prev); } else { _in.skipBits(ret); ret = 0; } case TYPE_FILL: case TYPE_FILL_DATA: case TYPE_EXT_DATA_ELEMENT: default: _in.skipBits(ret); ret = 0; break; } return ret; } private int decodeDynamicRangeInfo(IBitStream _in, int count) throws AACException { if(dri==null) dri = new DynamicRangeInfo(); int ret = count; int bandCount = 1; //pce tag if(dri.pceTagPresent = _in.readBool()) { dri.pceInstanceTag = _in.readBits(4); dri.tagReservedBits = _in.readBits(4); } //excluded channels if(dri.excludedChannelsPresent = _in.readBool()) { ret -= decodeExcludedChannels(_in); } //bands if(dri.bandsPresent = _in.readBool()) { dri.bandsIncrement = _in.readBits(4); dri.interpolationScheme = _in.readBits(4); ret -= 8; bandCount += dri.bandsIncrement; dri.bandTop = new int[bandCount]; for(int i = 0; i<bandCount; i++) { dri.bandTop[i] = _in.readBits(8); ret -= 8; } } //prog ref level if(dri.progRefLevelPresent = _in.readBool()) { dri.progRefLevel = _in.readBits(7); dri.progRefLevelReservedBits = _in.readBits(1); ret -= 8; } dri.dynRngSgn = new boolean[bandCount]; dri.dynRngCtl = new int[bandCount]; for(int i = 0; i<bandCount; i++) { dri.dynRngSgn[i] = _in.readBool(); dri.dynRngCtl[i] = _in.readBits(7); ret -= 8; } return ret; } private int decodeExcludedChannels(IBitStream _in) throws AACException { int i; int exclChs = 0; do { for(i = 0; i<7; i++) { dri.excludeMask[exclChs] = _in.readBool(); exclChs++; } } while(exclChs<57&&_in.readBool()); return (exclChs/7)*8; } }