public void sendToOutput(SampleBuffer buffer) { final boolean be = buffer.isBigEndian(); final int chs = data.length; final int mult = (sbrPresent && config.isSBREnabled()) ? 2 : 1; final int length = mult * config.getFrameLength(); final int freq = mult * config.getSampleFrequency().getFrequency(); byte[] b = buffer.getData(); if (b.length != chs * length * 2) b = new byte[chs * length * 2]; float[] cur; int i, j, off; short s; for (i = 0; i < chs; i++) { cur = data[i]; for (j = 0; j < length; j++) { s = (short) Math.max(Math.min(Math.round(cur[j]), Short.MAX_VALUE), Short.MIN_VALUE); off = (j * chs + i) * 2; if (be) { b[off] = (byte) ((s >> 8) & BYTE_MASK); b[off + 1] = (byte) (s & BYTE_MASK); } else { b[off + 1] = (byte) ((s >> 8) & BYTE_MASK); b[off] = (byte) (s & BYTE_MASK); } } } buffer.setData(b, freq, chs, 16, bitsRead); }
public void process(FilterBank filterBank) throws AACException { final Profile profile = config.getProfile(); final SampleFrequency sf = config.getSampleFrequency(); // final ChannelConfiguration channels = config.getChannelConfiguration(); int chs = config.getChannelConfiguration().getChannelCount(); if (chs == 1 && psPresent) chs++; final int mult = sbrPresent ? 2 : 1; // only reallocate if needed if (data == null || chs != data.length || (mult * config.getFrameLength()) != data[0].length) data = new float[chs][mult * config.getFrameLength()]; int channel = 0; Element e; SCE_LFE scelfe; CPE cpe; for (int i = 0; i < elements.length && channel < chs; i++) { e = elements[i]; if (e == null) continue; if (e instanceof SCE_LFE) { scelfe = (SCE_LFE) e; channel += processSingle(scelfe, filterBank, channel, profile, sf); } else if (e instanceof CPE) { cpe = (CPE) e; processPair(cpe, filterBank, channel, profile, sf); channel += 2; } else if (e instanceof CCE) { // applies invquant and save the result in the CCE ((CCE) e).process(); channel++; } } }
private void decodeFIL(BitStream in, Element prev) throws AACException { if (curFIL == MAX_ELEMENTS) throw new AACException("too much FIL elements"); if (fils[curFIL] == null) fils[curFIL] = new FIL(config.isSBRDownSampled()); fils[curFIL].decode(in, prev, config.getSampleFrequency(), config.isSBREnabled()); curFIL++; if (prev != null && prev.isSBRPresent()) { sbrPresent = true; if (!psPresent && prev.getSBR().isPSUsed()) psPresent = true; } }
public void decode(BitStream in) throws AACException { final int start = in.getPosition(); // should be 0 int type; Element prev = null; boolean content = true; if (!config.getProfile().isErrorResilientProfile()) { while (content && (type = in.readBits(3)) != ELEMENT_END) { switch (type) { case ELEMENT_SCE: case ELEMENT_LFE: LOGGER.finest("SCE"); prev = decodeSCE_LFE(in); break; case ELEMENT_CPE: LOGGER.finest("CPE"); prev = decodeCPE(in); break; case ELEMENT_CCE: LOGGER.finest("CCE"); decodeCCE(in); prev = null; break; case ELEMENT_DSE: LOGGER.finest("DSE"); decodeDSE(in); prev = null; break; case ELEMENT_PCE: LOGGER.finest("PCE"); decodePCE(in); prev = null; break; case ELEMENT_FIL: LOGGER.finest("FIL"); decodeFIL(in, prev); prev = null; break; } } LOGGER.finest("END"); content = false; prev = null; } else { // error resilient raw data block switch (config.getChannelConfiguration()) { case CHANNEL_CONFIG_MONO: decodeSCE_LFE(in); break; case CHANNEL_CONFIG_STEREO: decodeCPE(in); break; case CHANNEL_CONFIG_STEREO_PLUS_CENTER: decodeSCE_LFE(in); decodeCPE(in); break; case CHANNEL_CONFIG_STEREO_PLUS_CENTER_PLUS_REAR_MONO: decodeSCE_LFE(in); decodeCPE(in); decodeSCE_LFE(in); break; case CHANNEL_CONFIG_FIVE: decodeSCE_LFE(in); decodeCPE(in); decodeCPE(in); break; case CHANNEL_CONFIG_FIVE_PLUS_ONE: decodeSCE_LFE(in); decodeCPE(in); decodeCPE(in); decodeSCE_LFE(in); break; case CHANNEL_CONFIG_SEVEN_PLUS_ONE: decodeSCE_LFE(in); decodeCPE(in); decodeCPE(in); decodeCPE(in); decodeSCE_LFE(in); break; default: throw new AACException( "unsupported channel configuration for error resilience: " + config.getChannelConfiguration()); } } in.byteAlign(); bitsRead = in.getPosition() - start; }
private void processPair( CPE cpe, FilterBank filterBank, int channel, Profile profile, SampleFrequency sf) throws AACException { final ICStream ics1 = cpe.getLeftChannel(); final ICStream ics2 = cpe.getRightChannel(); final ICSInfo info1 = ics1.getInfo(); final ICSInfo info2 = ics2.getInfo(); final LTPrediction ltp1 = info1.getLTPrediction1(); final LTPrediction ltp2 = cpe.isCommonWindow() ? info1.getLTPrediction2() : info2.getLTPrediction1(); final int elementID = cpe.getElementInstanceTag(); // inverse quantization final float[] iqData1 = ics1.getInvQuantData(); final float[] iqData2 = ics2.getInvQuantData(); // MS if (cpe.isCommonWindow() && cpe.isMSMaskPresent()) MS.process(cpe, iqData1, iqData2); // main prediction if (profile.equals(Profile.AAC_MAIN)) { if (info1.isICPredictionPresent()) info1.getICPrediction().process(ics1, iqData1, sf); if (info2.isICPredictionPresent()) info2.getICPrediction().process(ics2, iqData2, sf); } // IS IS.process(cpe, iqData1, iqData2); // LTP if (LTPrediction.isLTPProfile(profile)) { if (info1.isLTPrediction1Present()) ltp1.process(ics1, iqData1, filterBank, sf); if (cpe.isCommonWindow() && info1.isLTPrediction2Present()) ltp2.process(ics2, iqData2, filterBank, sf); else if (info2.isLTPrediction1Present()) ltp2.process(ics2, iqData2, filterBank, sf); } // dependent coupling processDependentCoupling(true, elementID, CCE.BEFORE_TNS, iqData1, iqData2); // TNS if (ics1.isTNSDataPresent()) ics1.getTNS().process(ics1, iqData1, sf, false); if (ics2.isTNSDataPresent()) ics2.getTNS().process(ics2, iqData2, sf, false); // dependent coupling processDependentCoupling(true, elementID, CCE.AFTER_TNS, iqData1, iqData2); // filterbank filterBank.process( info1.getWindowSequence(), info1.getWindowShape(ICSInfo.CURRENT), info1.getWindowShape(ICSInfo.PREVIOUS), iqData1, data[channel], channel); filterBank.process( info2.getWindowSequence(), info2.getWindowShape(ICSInfo.CURRENT), info2.getWindowShape(ICSInfo.PREVIOUS), iqData2, data[channel + 1], channel + 1); if (LTPrediction.isLTPProfile(profile)) { ltp1.updateState(data[channel], filterBank.getOverlap(channel), profile); ltp2.updateState(data[channel + 1], filterBank.getOverlap(channel + 1), profile); } // independent coupling processIndependentCoupling(true, elementID, data[channel], data[channel + 1]); // gain control if (ics1.isGainControlPresent()) ics1.getGainControl() .process( iqData1, info1.getWindowShape(ICSInfo.CURRENT), info1.getWindowShape(ICSInfo.PREVIOUS), info1.getWindowSequence()); if (ics2.isGainControlPresent()) ics2.getGainControl() .process( iqData2, info2.getWindowShape(ICSInfo.CURRENT), info2.getWindowShape(ICSInfo.PREVIOUS), info2.getWindowSequence()); // SBR if (sbrPresent && config.isSBREnabled()) { if (data[channel].length == config.getFrameLength()) LOGGER.log(Level.WARNING, "SBR data present, but buffer has normal size!"); cpe.getSBR().process(data[channel], data[channel + 1]); } }
private int processSingle( SCE_LFE scelfe, FilterBank filterBank, int channel, Profile profile, SampleFrequency sf) throws AACException { final ICStream ics = scelfe.getICStream(); final ICSInfo info = ics.getInfo(); final LTPrediction ltp = info.getLTPrediction1(); final int elementID = scelfe.getElementInstanceTag(); // inverse quantization final float[] iqData = ics.getInvQuantData(); // prediction if (profile.equals(Profile.AAC_MAIN) && info.isICPredictionPresent()) info.getICPrediction().process(ics, iqData, sf); if (LTPrediction.isLTPProfile(profile) && info.isLTPrediction1Present()) ltp.process(ics, iqData, filterBank, sf); // dependent coupling processDependentCoupling(false, elementID, CCE.BEFORE_TNS, iqData, null); // TNS if (ics.isTNSDataPresent()) ics.getTNS().process(ics, iqData, sf, false); // dependent coupling processDependentCoupling(false, elementID, CCE.AFTER_TNS, iqData, null); // filterbank filterBank.process( info.getWindowSequence(), info.getWindowShape(ICSInfo.CURRENT), info.getWindowShape(ICSInfo.PREVIOUS), iqData, data[channel], channel); if (LTPrediction.isLTPProfile(profile)) ltp.updateState(data[channel], filterBank.getOverlap(channel), profile); // dependent coupling processIndependentCoupling(false, elementID, data[channel], null); // gain control if (ics.isGainControlPresent()) ics.getGainControl() .process( iqData, info.getWindowShape(ICSInfo.CURRENT), info.getWindowShape(ICSInfo.PREVIOUS), info.getWindowSequence()); // SBR int chs = 1; if (sbrPresent && config.isSBREnabled()) { if (data[channel].length == config.getFrameLength()) LOGGER.log(Level.WARNING, "SBR data present, but buffer has normal size!"); final SBR sbr = scelfe.getSBR(); if (sbr.isPSUsed()) { chs = 2; scelfe.getSBR().process(data[channel], data[channel + 1]); } else scelfe.getSBR().process(data[channel], null); } return chs; }
private void decodePCE(BitStream in) throws AACException { pce.decode(in); config.setProfile(pce.getProfile()); config.setSampleFrequency(pce.getSampleFrequency()); config.setChannelConfiguration(ChannelConfiguration.forInt(pce.getChannelCount())); }
private void decodeCCE(BitStream in) throws AACException { if (curCCE == MAX_ELEMENTS) throw new AACException("too much CCE elements"); if (cces[curCCE] == null) cces[curCCE] = new CCE(config.getFrameLength()); cces[curCCE].decode(in, config); curCCE++; }
private Element decodeCPE(BitStream in) throws AACException { if (elements[curElem] == null) elements[curElem] = new CPE(config.getFrameLength()); ((CPE) elements[curElem]).decode(in, config); curElem++; return elements[curElem - 1]; }