/*
* Copyright (C) 2011 in-somnia
*
* This file is part of JAAD.
*
* JAAD 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 3 of the
* License, or (at your option) any later version.
*
* JAAD 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, see <http://www.gnu.org/licenses/>.
*/
package net.sourceforge.jaad.aac.syntax;
import net.sourceforge.jaad.aac.AACException;
import net.sourceforge.jaad.aac.SampleFrequency;
class FIL extends Element implements Constants {
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(BitStream in, Element prev, SampleFrequency sf) 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);
}
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(BitStream in, int count, Element prev, SampleFrequency sf) 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(prev instanceof SCE_LFE||prev instanceof CPE||prev instanceof CCE) {
prev.decodeSBR(in, sf, ret, (prev instanceof CPE), (type==TYPE_SBR_DATA_CRC), downSampledSBR);
ret = 0;
break;
}
else throw new AACException("SBR applied on unexpected element: "+prev);
case TYPE_FILL:
case TYPE_FILL_DATA:
case TYPE_EXT_DATA_ELEMENT:
default:
in.skipBits(ret);
ret = 0;
break;
}
return ret;
}
private int decodeDynamicRangeInfo(BitStream 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(BitStream 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;
}
}