net.sourceforge.jaad.aac.syntax.ICStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcodec Show documentation
Show all versions of jcodec Show documentation
Pure Java implementation of video/audio codecs and formats
package net.sourceforge.jaad.aac.syntax;
import java.util.Arrays;
import org.jcodec.common.logging.Logger;
import net.sourceforge.jaad.aac.AACException;
import net.sourceforge.jaad.aac.ChannelConfiguration;
import net.sourceforge.jaad.aac.DecoderConfig;
import net.sourceforge.jaad.aac.error.RVLC;
import net.sourceforge.jaad.aac.gain.GainControl;
import net.sourceforge.jaad.aac.huffman.HCB;
import net.sourceforge.jaad.aac.huffman.Huffman;
import net.sourceforge.jaad.aac.tools.TNS;
/**
* 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
*/
//TODO: apply pulse data
public class ICStream implements SyntaxConstants, HCB, ScaleFactorTable, IQTable {
private static final int SF_DELTA = 60;
private static final int SF_OFFSET = 200;
private static int randomState = 0x1F2E3D4C;
private final int frameLength;
//always needed
private final ICSInfo info;
private final int[] sfbCB;
private final int[] sectEnd;
private final float[] data;
private final float[] scaleFactors;
private int globalGain;
private boolean pulseDataPresent, tnsDataPresent, gainControlPresent;
//only allocated if needed
private TNS tns;
private GainControl gainControl;
private int[] pulseOffset, pulseAmp;
private int pulseCount;
private int pulseStartSWB;
//error resilience
private boolean noiseUsed;
private int reorderedSpectralDataLen, longestCodewordLen;
private RVLC rvlc;
public ICStream(int frameLength) {
this.frameLength = frameLength;
info = new ICSInfo(frameLength);
sfbCB = new int[MAX_SECTIONS];
sectEnd = new int[MAX_SECTIONS];
data = new float[frameLength];
scaleFactors = new float[MAX_SECTIONS];
}
/* ========= decoding ========== */
public void decode(IBitStream _in, boolean commonWindow, DecoderConfig conf) throws AACException {
if(conf.isScalefactorResilienceUsed()&&rvlc==null) rvlc = new RVLC();
final boolean er = conf.getProfile().isErrorResilientProfile();
globalGain = _in.readBits(8);
if(!commonWindow) info.decode(_in, conf, commonWindow);
decodeSectionData(_in, conf.isSectionDataResilienceUsed());
//if(conf.isScalefactorResilienceUsed()) rvlc.decode(_in, this, scaleFactors);
/*else*/ decodeScaleFactors(_in);
pulseDataPresent = _in.readBool();
if(pulseDataPresent) {
if(info.isEightShortFrame()) throw new AACException("pulse data not allowed for short frames");
Logger.debug("PULSE");
decodePulseData(_in);
}
tnsDataPresent = _in.readBool();
if(tnsDataPresent&&!er) {
if(tns==null) tns = new TNS();
tns.decode(_in, info);
}
gainControlPresent = _in.readBool();
if(gainControlPresent) {
if(gainControl==null) gainControl = new GainControl(frameLength);
Logger.debug("GAIN");
gainControl.decode(_in, info.getWindowSequence());
}
//RVLC spectral data
//if(conf.isScalefactorResilienceUsed()) rvlc.decodeScalefactors(this, _in, scaleFactors);
if(conf.isSpectralDataResilienceUsed()) {
int max = (conf.getChannelConfiguration()==ChannelConfiguration.CHANNEL_CONFIG_STEREO) ? 6144 : 12288;
reorderedSpectralDataLen = Math.max(_in.readBits(14), max);
longestCodewordLen = Math.max(_in.readBits(6), 49);
//HCR.decodeReorderedSpectralData(this, _in, data, conf.isSectionDataResilienceUsed());
}
else decodeSpectralData(_in);
}
public void decodeSectionData(IBitStream _in, boolean sectionDataResilienceUsed) throws AACException {
Arrays.fill(sfbCB, 0);
Arrays.fill(sectEnd, 0);
final int bits = info.isEightShortFrame() ? 3 : 5;
final int escVal = (1<maxSFB) throw new AACException("too many bands: "+end+", allowed: "+maxSFB);
for(; k=info.getSWBCount()) throw new AACException("pulse SWB out of range: "+pulseStartSWB+" > "+info.getSWBCount());
if(pulseOffset==null||pulseCount!=pulseOffset.length) {
//only reallocate if needed
pulseOffset = new int[pulseCount];
pulseAmp = new int[pulseCount];
}
pulseOffset[0] = info.getSWBOffsets()[pulseStartSWB];
pulseOffset[0] += _in.readBits(5);
pulseAmp[0] = _in.readBits(4);
for(int i = 1; i1023) throw new AACException("pulse offset out of range: "+pulseOffset[0]);
pulseAmp[i] = _in.readBits(4);
}
}
public void decodeScaleFactors(IBitStream _in) throws AACException {
final int windowGroups = info.getWindowGroupCount();
final int maxSFB = info.getMaxSFB();
//0: spectrum, 1: noise, 2: intensity
final int[] offset = {globalGain, globalGain-90, 0};
int tmp;
boolean noiseFlag = true;
int sfb, idx = 0;
for(int g = 0; g255) throw new AACException("scalefactor out of range: "+offset[0]);
scaleFactors[idx] = SCALEFACTOR_TABLE[offset[0]-100+SF_OFFSET];
}
break;
}
}
}
}
private void decodeSpectralData(IBitStream _in) throws AACException {
Arrays.fill(data, 0);
final int maxSFB = info.getMaxSFB();
final int windowGroups = info.getWindowGroupCount();
final int[] offsets = info.getSWBOffsets();
final int[] buf = new int[4];
int sfb, j, k, w, hcb, off, width, num;
int groupOff = 0, idx = 0;
for(int g = 0; g=FIRST_PAIR_HCB) ? 2 : 4;
for(k = 0; k0) ? IQ_TABLE[buf[j]] : -IQ_TABLE[-buf[j]];
data[off+k+j] *= scaleFactors[idx];
}
}
}
}
}
groupOff += groupLen<<7;
}
}
/* =========== gets ============ */
/**
* Does inverse quantization and applies the scale factors on the decoded
* data. After this the noiseless decoding is finished and the decoded data
* is returned.
* @return the inverse quantized and scaled data
*/
public float[] getInvQuantData() throws AACException {
return data;
}
public ICSInfo getInfo() {
return info;
}
public int[] getSectEnd() {
return sectEnd;
}
public int[] getSfbCB() {
return sfbCB;
}
public float[] getScaleFactors() {
return scaleFactors;
}
public boolean isTNSDataPresent() {
return tnsDataPresent;
}
public TNS getTNS() {
return tns;
}
public int getGlobalGain() {
return globalGain;
}
public boolean isNoiseUsed() {
return noiseUsed;
}
public int getLongestCodewordLength() {
return longestCodewordLen;
}
public int getReorderedSpectralDataLength() {
return reorderedSpectralDataLen;
}
public boolean isGainControlPresent() {
return gainControlPresent;
}
public GainControl getGainControl() {
return gainControl;
}
}