net.sourceforge.jaad.aac.ps.PS 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.ps;
import net.sourceforge.jaad.aac.AACException;
import net.sourceforge.jaad.aac.SampleFrequency;
import net.sourceforge.jaad.aac.syntax.IBitStream;
/**
* 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
*/
public class PS implements PSConstants, PSTables, PSHuffmanTables {
/* bitstream parameters */
boolean enable_iid, enable_icc, enable_ext;
int iid_mode;
int icc_mode;
int nr_iid_par;
int nr_ipdopd_par;
int nr_icc_par;
int frame_class;
int num_env;
int[] border_position;
boolean[] iid_dt;
boolean[] icc_dt;
boolean enable_ipdopd;
int ipd_mode;
boolean[] ipd_dt;
boolean[] opd_dt;
/* indices */
int[] iid_index_prev;
int[] icc_index_prev;
int[] ipd_index_prev;
int[] opd_index_prev;
int[][] iid_index;
int[][] icc_index;
int[][] ipd_index;
int[][] opd_index;
int[] ipd_index_1;
int[] opd_index_1;
int[] ipd_index_2;
int[] opd_index_2;
/* ps data was correctly read */
int ps_data_available;
/* a header has been read */
public boolean header_read;
/* hybrid filterbank parameters */
PSFilterbank hyb;
boolean use34hybrid_bands;
int numTimeSlotsRate;
int num_groups;
int num_hybrid_groups;
int nr_par_bands;
int nr_allpass_bands;
int decay_cutoff;
int[] group_border;
int[] map_group2bk;
/* filter delay handling */
int saved_delay;
int[] delay_buf_index_ser;
int[] num_sample_delay_ser;
int[] delay_D;
int[] delay_buf_index_delay;
float[][][] delay_Qmf; /* 14 samples delay max, 64 QMF channels */
float[][][] delay_SubQmf; /* 2 samples delay max (SubQmf is always allpass filtered) */
float[][][][] delay_Qmf_ser; /* 5 samples delay max (table 8.34), 64 QMF channels */
float[][][][] delay_SubQmf_ser; /* 5 samples delay max (table 8.34) */
/* transients */
float alpha_decay;
float alpha_smooth;
float[] P_PeakDecayNrg;
float[] P_prev;
float[] P_SmoothPeakDecayDiffNrg_prev;
/* mixing and phase */
float[][] h11_prev;
float[][] h12_prev;
float[][] h21_prev;
float[][] h22_prev;
int phase_hist;
float[][][] ipd_prev;
float[][][] opd_prev;
public PS(SampleFrequency sr, int numTimeSlotsRate) {
this.border_position = new int[MAX_PS_ENVELOPES+1];
this.iid_dt = new boolean[MAX_PS_ENVELOPES];
this.icc_dt = new boolean[MAX_PS_ENVELOPES];
this.ipd_dt = new boolean[MAX_PS_ENVELOPES];
this.opd_dt = new boolean[MAX_PS_ENVELOPES];
this.iid_index_prev = new int[34];
this.icc_index_prev = new int[34];
this.ipd_index_prev = new int[17];
this.opd_index_prev = new int[17];
this.iid_index = new int[MAX_PS_ENVELOPES][34];
this.icc_index = new int[MAX_PS_ENVELOPES][34];
this.ipd_index = new int[MAX_PS_ENVELOPES][17];
this.opd_index = new int[MAX_PS_ENVELOPES][17];
this.ipd_index_1 = new int[17];
this.opd_index_1 = new int[17];
this.ipd_index_2 = new int[17];
this.opd_index_2 = new int[17];
this.delay_buf_index_ser = new int[NO_ALLPASS_LINKS];
this.num_sample_delay_ser = new int[NO_ALLPASS_LINKS];
this.delay_D = new int[64];
this.delay_buf_index_delay = new int[64];
this.delay_Qmf = new float[14][64][2]; /* 14 samples delay max, 64 QMF channels */
this.delay_SubQmf = new float[2][32][2]; /* 2 samples delay max (SubQmf is always allpass filtered) */
this.delay_Qmf_ser = new float[NO_ALLPASS_LINKS][5][64][2]; /* 5 samples delay max (table 8.34), 64 QMF channels */
this.delay_SubQmf_ser = new float[NO_ALLPASS_LINKS][5][32][2]; /* 5 samples delay max (table 8.34) */
this.P_PeakDecayNrg = new float[34];
this.P_prev = new float[34];
this.P_SmoothPeakDecayDiffNrg_prev = new float[34];
this.h11_prev = new float[50][2];
this.h12_prev = new float[50][2];
this.h21_prev = new float[50][2];
this.h22_prev = new float[50][2];
this.ipd_prev = new float[20][2][2];
this.opd_prev = new float[20][2][2];
int i;
int short_delay_band;
hyb = new PSFilterbank(numTimeSlotsRate);
this.numTimeSlotsRate = numTimeSlotsRate;
this.ps_data_available = 0;
/* delay stuff*/
this.saved_delay = 0;
for(i = 0; i<64; i++) {
this.delay_buf_index_delay[i] = 0;
}
for(i = 0; i7) {
int ps_extension_id = ld.readBits(2);
num_bits_left -= 2;
num_bits_left -= ps_extension(ld, ps_extension_id, num_bits_left);
}
ld.skipBits(num_bits_left);
}
int bits2 = (int) (ld.getPosition()-bits);
this.ps_data_available = 1;
return bits2;
}
private int ps_extension(IBitStream ld,
int ps_extension_id,
int num_bits_left) throws AACException {
int n;
long bits = ld.getPosition();
if(ps_extension_id==0) {
this.enable_ipdopd = ld.readBool();
if(this.enable_ipdopd) {
for(n = 0; n=0) {
bit = ld.readBit();
index = t_huff[index][bit];
}
return index+31;
}
/* limits the value i to the range [min,max] */
private int delta_clip(int i, int min, int max) {
if(imax) return max;
else return i;
}
/* delta decode array */
private void delta_decode(boolean enable, int[] index, int[] index_prev,
boolean dt_flag, int nr_par, int stride,
int min_index, int max_index) {
int i;
if(enable) {
if(!dt_flag) {
/* delta coded in frequency direction */
index[0] = 0+index[0];
index[0] = delta_clip(index[0], min_index, max_index);
for(i = 1; i0; i--) {
index[i] = index[i>>1];
}
}
}
/* delta modulo decode array */
/* in: log2 value of the modulo value to allow using AND instead of MOD */
private void delta_modulo_decode(boolean enable, int[] index, int[] index_prev,
boolean dt_flag, int nr_par, int stride,
int and_modulo) {
int i;
if(enable) {
if(!dt_flag) {
/* delta coded in frequency direction */
index[0] = 0+index[0];
index[0] &= and_modulo;
for(i = 1; i0; i--) {
index[i] = index[i>>1];
}
}
}
private void map20indexto34(int[] index, int bins) {
//index[0] = index[0];
index[1] = (index[0]+index[1])/2;
index[2] = index[1];
index[3] = index[2];
index[4] = (index[2]+index[3])/2;
index[5] = index[3];
index[6] = index[4];
index[7] = index[4];
index[8] = index[5];
index[9] = index[5];
index[10] = index[6];
index[11] = index[7];
index[12] = index[8];
index[13] = index[8];
index[14] = index[9];
index[15] = index[9];
index[16] = index[10];
if(bins==34) {
index[17] = index[11];
index[18] = index[12];
index[19] = index[13];
index[20] = index[14];
index[21] = index[14];
index[22] = index[15];
index[23] = index[15];
index[24] = index[16];
index[25] = index[16];
index[26] = index[17];
index[27] = index[17];
index[28] = index[18];
index[29] = index[18];
index[30] = index[18];
index[31] = index[18];
index[32] = index[19];
index[33] = index[19];
}
}
/* parse the bitstream data decoded in ps_data() */
private void ps_data_decode() {
int env, bin;
/* ps data not available, use data from previous frame */
if(this.ps_data_available==0) {
this.num_env = 0;
}
for(env = 0; envthr) {
this.border_position[env] = thr;
}
else {
thr = this.border_position[env-1]+1;
if(this.border_position[env]this.nr_allpass_bands&&gr>=this.num_hybrid_groups) {
/* delay */
/* never hybrid subbands here, always QMF subbands */
tmp[0] = this.delay_Qmf[this.delay_buf_index_delay[sb]][sb][0];
tmp[1] = this.delay_Qmf[this.delay_buf_index_delay[sb]][sb][1];
R0[0] = tmp[0];
R0[1] = tmp[1];
this.delay_Qmf[this.delay_buf_index_delay[sb]][sb][0] = inputLeft[0];
this.delay_Qmf[this.delay_buf_index_delay[sb]][sb][1] = inputLeft[1];
}
else {
/* allpass filter */
//int m;
float[] Phi_Fract = new float[2];
/* fetch parameters */
if(gr=2) {
temp_delay = 0;
}
/* update delay indices */
if(sb>this.nr_allpass_bands&&gr>=this.num_hybrid_groups) {
/* delay_D depends on the samplerate, it can hold the values 14 and 1 */
if(++this.delay_buf_index_delay[sb]>=this.delay_D[sb]) {
this.delay_buf_index_delay[sb] = 0;
}
}
for(m = 0; m=this.num_sample_delay_ser[m]) {
temp_delay_ser[m] = 0;
}
}
}
}
}
/* update delay indices */
this.saved_delay = temp_delay;
for(m = 0; m=3) {
no_iid_steps = 15;
sf_iid = sf_iid_fine;
}
else {
no_iid_steps = 7;
sf_iid = sf_iid_normal;
}
if(this.ipd_mode==0||this.ipd_mode==3) {
nr_ipdopd_par = 11; /* resolution */
}
else {
nr_ipdopd_par = this.nr_ipdopd_par;
}
for(gr = 0; gr=3) {
if(this.iid_index[env][bk]<0) {
cosb = cos_betas_fine[-this.iid_index[env][bk]][this.icc_index[env][bk]];
sinb = -sin_betas_fine[-this.iid_index[env][bk]][this.icc_index[env][bk]];
}
else {
cosb = cos_betas_fine[this.iid_index[env][bk]][this.icc_index[env][bk]];
sinb = sin_betas_fine[this.iid_index[env][bk]][this.icc_index[env][bk]];
}
}
else {
if(this.iid_index[env][bk]<0) {
cosb = cos_betas_normal[-this.iid_index[env][bk]][this.icc_index[env][bk]];
sinb = -sin_betas_normal[-this.iid_index[env][bk]][this.icc_index[env][bk]];
}
else {
cosb = cos_betas_normal[this.iid_index[env][bk]][this.icc_index[env][bk]];
sinb = sin_betas_normal[this.iid_index[env][bk]][this.icc_index[env][bk]];
}
}
ab1 = (cosb*cosa);
ab2 = (sinb*sina);
ab3 = (sinb*cosa);
ab4 = (cosb*sina);
/* h_xy: COEF */
h11[0] = (c_2*(ab1-ab2));
h12[0] = (c_1*(ab1+ab2));
h21[0] = (c_2*(ab3+ab4));
h22[0] = (c_1*(ab3-ab4));
}
else {
/* type 'B' mixing as described in 8.6.4.6.2.2 */
float sina, cosa;
float cosg, sing;
if(this.iid_mode>=3) {
int abs_iid = Math.abs(this.iid_index[env][bk]);
cosa = sincos_alphas_B_fine[no_iid_steps+this.iid_index[env][bk]][this.icc_index[env][bk]];
sina = sincos_alphas_B_fine[30-(no_iid_steps+this.iid_index[env][bk])][this.icc_index[env][bk]];
cosg = cos_gammas_fine[abs_iid][this.icc_index[env][bk]];
sing = sin_gammas_fine[abs_iid][this.icc_index[env][bk]];
}
else {
int abs_iid = Math.abs(this.iid_index[env][bk]);
cosa = sincos_alphas_B_normal[no_iid_steps+this.iid_index[env][bk]][this.icc_index[env][bk]];
sina = sincos_alphas_B_normal[14-(no_iid_steps+this.iid_index[env][bk])][this.icc_index[env][bk]];
cosg = cos_gammas_normal[abs_iid][this.icc_index[env][bk]];
sing = sin_gammas_normal[abs_iid][this.icc_index[env][bk]];
}
h11[0] = (COEF_SQRT2*(cosa*cosg));
h12[0] = (COEF_SQRT2*(sina*cosg));
h21[0] = (COEF_SQRT2*(-cosa*sing));
h22[0] = (COEF_SQRT2*(sina*sing));
}
/* calculate phase rotation parameters H_xy */
/* note that the imaginary part of these parameters are only calculated when
IPD and OPD are enabled
*/
if((this.enable_ipdopd)&&(bk