
net.sourceforge.jaad.aac.sbr.SBR Maven / Gradle / Ivy
package net.sourceforge.jaad.aac.sbr;
import java.util.Arrays;
import net.sourceforge.jaad.aac.AACException;
import net.sourceforge.jaad.aac.SampleFrequency;
import net.sourceforge.jaad.aac.ps.PS;
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 SBR implements SBRConstants, net.sourceforge.jaad.aac.syntax.SyntaxConstants, HuffmanTables {
private final boolean downSampledSBR;
final SampleFrequency sample_rate;
int maxAACLine;
int rate;
boolean just_seeked;
int ret;
boolean[] amp_res;
int k0;
int kx;
int M;
int N_master;
int N_high;
int N_low;
int N_Q;
int[] N_L;
int[] n;
int[] f_master;
int[][] f_table_res;
int[] f_table_noise;
int[][] f_table_lim;
int[] table_map_k_to_g;
int[] abs_bord_lead;
int[] abs_bord_trail;
int[] n_rel_lead;
int[] n_rel_trail;
int[] L_E;
int[] L_E_prev;
int[] L_Q;
int[][] t_E;
int[][] t_Q;
int[][] f;
int[] f_prev;
float[][][] G_temp_prev;
float[][][] Q_temp_prev;
int[] GQ_ringbuf_index;
int[][][] E;
int[][] E_prev;
float[][][] E_orig;
float[][][] E_curr;
int[][][] Q;
float[][][] Q_div;
float[][][] Q_div2;
int[][] Q_prev;
int[] l_A;
int[] l_A_prev;
int[][] bs_invf_mode;
int[][] bs_invf_mode_prev;
float[][] bwArray;
float[][] bwArray_prev;
int noPatches;
int[] patchNoSubbands;
int[] patchStartSubband;
int[][] bs_add_harmonic;
int[][] bs_add_harmonic_prev;
int[] index_noise_prev;
int[] psi_is_prev;
int bs_start_freq_prev;
int bs_stop_freq_prev;
int bs_xover_band_prev;
int bs_freq_scale_prev;
boolean bs_alter_scale_prev;
int bs_noise_bands_prev;
int[] prevEnvIsShort;
int kx_prev;
int bsco;
int bsco_prev;
int M_prev;
boolean Reset;
int frame;
int header_count;
boolean stereo;
AnalysisFilterbank[] qmfa;
SynthesisFilterbank[] qmfs;
float[][][][] Xsbr;
int numTimeSlotsRate;
int numTimeSlots;
int tHFGen;
int tHFAdj;
PS ps;
boolean ps_used;
boolean psResetFlag;
/* to get it compiling */
/* we'll see during the coding of all the tools, whether
these are all used or not.
*/
boolean bs_header_flag;
int bs_crc_flag;
int bs_sbr_crc_bits;
int bs_protocol_version;
boolean bs_amp_res;
int bs_start_freq;
int bs_stop_freq;
int bs_xover_band;
int bs_freq_scale;
boolean bs_alter_scale;
int bs_noise_bands;
int bs_limiter_bands;
int bs_limiter_gains;
boolean bs_interpol_freq;
boolean bs_smoothing_mode;
int bs_samplerate_mode;
boolean[] bs_add_harmonic_flag;
boolean[] bs_add_harmonic_flag_prev;
boolean bs_extended_data;
int bs_extension_id;
int bs_extension_data;
boolean bs_coupling;
int[] bs_frame_class;
int[][] bs_rel_bord;
int[][] bs_rel_bord_0;
int[][] bs_rel_bord_1;
int[] bs_pointer;
int[] bs_abs_bord_0;
int[] bs_abs_bord_1;
int[] bs_num_rel_0;
int[] bs_num_rel_1;
int[][] bs_df_env;
int[][] bs_df_noise;
public SBR(boolean smallFrames, boolean stereo, SampleFrequency sample_rate, boolean downSampledSBR) {
this.amp_res = new boolean[2];
this.N_L = new int[4];
this.n = new int[2];
this.f_master = new int[64];
this.f_table_res = new int[2][64];
this.f_table_noise = new int[64];
this.f_table_lim = new int[4][64];
this.table_map_k_to_g = new int[64];
this.abs_bord_lead = new int[2];
this.abs_bord_trail = new int[2];
this.n_rel_lead = new int[2];
this.n_rel_trail = new int[2];
this.L_E = new int[2];
this.L_E_prev = new int[2];
this.L_Q = new int[2];
this.t_E = new int[2][MAX_L_E+1];
this.t_Q = new int[2][3];
this.f = new int[2][MAX_L_E+1];
this.f_prev = new int[2];
this.G_temp_prev = new float[2][5][64];
this.Q_temp_prev = new float[2][5][64];
this.GQ_ringbuf_index = new int[2];
this.E = new int[2][64][MAX_L_E];
this.E_prev = new int[2][64];
this.E_orig = new float[2][64][MAX_L_E];
this.E_curr = new float[2][64][MAX_L_E];
this.Q = new int[2][64][2];
this.Q_div = new float[2][64][2];
this.Q_div2 = new float[2][64][2];
this.Q_prev = new int[2][64];
this.l_A = new int[2];
this.l_A_prev = new int[2];
this.bs_invf_mode = new int[2][MAX_L_E];
this.bs_invf_mode_prev = new int[2][MAX_L_E];
this.bwArray = new float[2][64];
this.bwArray_prev = new float[2][64];
this.patchNoSubbands = new int[64];
this.patchStartSubband = new int[64];
this.bs_add_harmonic = new int[2][64];
this.bs_add_harmonic_prev = new int[2][64];
this.index_noise_prev = new int[2];
this.psi_is_prev = new int[2];
this.prevEnvIsShort = new int[2];
this.qmfa = new AnalysisFilterbank[2];
this.qmfs = new SynthesisFilterbank[2];
this.Xsbr = new float[2][MAX_NTSRHFG][64][2];
this.bs_add_harmonic_flag = new boolean[2];
this.bs_add_harmonic_flag_prev = new boolean[2];
this.bs_frame_class = new int[2];
this.bs_rel_bord = new int[2][9];
this.bs_rel_bord_0 = new int[2][9];
this.bs_rel_bord_1 = new int[2][9];
this.bs_pointer = new int[2];
this.bs_abs_bord_0 = new int[2];
this.bs_abs_bord_1 = new int[2];
this.bs_num_rel_0 = new int[2];
this.bs_num_rel_1 = new int[2];
this.bs_df_env = new int[2][9];
this.bs_df_noise = new int[2][3];
this.downSampledSBR = downSampledSBR;
this.stereo = stereo;
this.sample_rate = sample_rate;
this.bs_freq_scale = 2;
this.bs_alter_scale = true;
this.bs_noise_bands = 2;
this.bs_limiter_bands = 2;
this.bs_limiter_gains = 2;
this.bs_interpol_freq = true;
this.bs_smoothing_mode = true;
this.bs_start_freq = 5;
this.bs_amp_res = true;
this.bs_samplerate_mode = 1;
this.prevEnvIsShort[0] = -1;
this.prevEnvIsShort[1] = -1;
this.header_count = 0;
this.Reset = true;
this.tHFGen = T_HFGEN;
this.tHFAdj = T_HFADJ;
this.bsco = 0;
this.bsco_prev = 0;
this.M_prev = 0;
/* force sbr reset */
this.bs_start_freq_prev = -1;
if(smallFrames) {
this.numTimeSlotsRate = RATE*NO_TIME_SLOTS_960;
this.numTimeSlots = NO_TIME_SLOTS_960;
}
else {
this.numTimeSlotsRate = RATE*NO_TIME_SLOTS;
this.numTimeSlots = NO_TIME_SLOTS;
}
this.GQ_ringbuf_index[0] = 0;
this.GQ_ringbuf_index[1] = 0;
if(stereo) {
/* stereo */
int j;
this.qmfa[0] = new AnalysisFilterbank(32);
this.qmfa[1] = new AnalysisFilterbank(32);
this.qmfs[0] = new SynthesisFilterbank((downSampledSBR) ? 32 : 64);
this.qmfs[1] = new SynthesisFilterbank((downSampledSBR) ? 32 : 64);
}
else {
/* mono */
this.qmfa[0] = new AnalysisFilterbank(32);
this.qmfs[0] = new SynthesisFilterbank((downSampledSBR) ? 32 : 64);
this.qmfs[1] = null;
}
}
void sbrReset() {
int j;
if(this.qmfa[0]!=null) qmfa[0].reset();
if(this.qmfa[1]!=null) qmfa[1].reset();
if(this.qmfs[0]!=null) qmfs[0].reset();
if(this.qmfs[1]!=null) qmfs[1].reset();
for(j = 0; j<5; j++) {
if(this.G_temp_prev[0][j]!=null) Arrays.fill(G_temp_prev[0][j], 0);
if(this.G_temp_prev[1][j]!=null) Arrays.fill(G_temp_prev[1][j], 0);
if(this.Q_temp_prev[0][j]!=null) Arrays.fill(Q_temp_prev[0][j], 0);
if(this.Q_temp_prev[1][j]!=null) Arrays.fill(Q_temp_prev[1][j], 0);
}
for(int i = 0; i<40; i++) {
for(int k = 0; k<64; k++) {
Xsbr[0][i][j][0] = 0;
Xsbr[0][i][j][1] = 0;
Xsbr[1][i][j][0] = 0;
Xsbr[1][i][j][1] = 0;
}
}
this.GQ_ringbuf_index[0] = 0;
this.GQ_ringbuf_index[1] = 0;
this.header_count = 0;
this.Reset = true;
this.L_E_prev[0] = 0;
this.L_E_prev[1] = 0;
this.bs_freq_scale = 2;
this.bs_alter_scale = true;
this.bs_noise_bands = 2;
this.bs_limiter_bands = 2;
this.bs_limiter_gains = 2;
this.bs_interpol_freq = true;
this.bs_smoothing_mode = true;
this.bs_start_freq = 5;
this.bs_amp_res = true;
this.bs_samplerate_mode = 1;
this.prevEnvIsShort[0] = -1;
this.prevEnvIsShort[1] = -1;
this.bsco = 0;
this.bsco_prev = 0;
this.M_prev = 0;
this.bs_start_freq_prev = -1;
this.f_prev[0] = 0;
this.f_prev[1] = 0;
for(j = 0; j=48000) {
if((k2-this.k0)>32)
result += 1;
}
else if(this.sample_rate.getFrequency()<=32000) {
if((k2-this.k0)>48)
result += 1;
}
else { /* (sbr.sample_rate == 44100) */
if((k2-this.k0)>45)
result += 1;
}
if(freq_scale==0) {
result += FBT.master_frequency_table_fs0(this, this.k0, k2, alter_scale);
}
else {
result += FBT.master_frequency_table(this, this.k0, k2, freq_scale, alter_scale);
}
result += FBT.derived_frequency_table(this, xover_band, k2);
result = (result>0) ? 1 : 0;
return result;
}
/* table 2 */
public int decode(IBitStream ld, int cnt) throws AACException {
int result = 0;
int num_align_bits = 0;
long num_sbr_bits1 = ld.getPosition();
int num_sbr_bits2;
int saved_start_freq, saved_samplerate_mode;
int saved_stop_freq, saved_freq_scale;
int saved_xover_band;
boolean saved_alter_scale;
int bs_extension_type = ld.readBits(4);
if(bs_extension_type==EXT_SBR_DATA_CRC) {
this.bs_sbr_crc_bits = ld.readBits(10);
}
/* save old header values, in case the new ones are corrupted */
saved_start_freq = this.bs_start_freq;
saved_samplerate_mode = this.bs_samplerate_mode;
saved_stop_freq = this.bs_stop_freq;
saved_freq_scale = this.bs_freq_scale;
saved_alter_scale = this.bs_alter_scale;
saved_xover_band = this.bs_xover_band;
this.bs_header_flag = ld.readBool();
if(this.bs_header_flag)
sbr_header(ld);
/* Reset? */
sbr_reset();
/* first frame should have a header */
//if (!(sbr.frame == 0 && sbr.bs_header_flag == 0))
if(this.header_count!=0) {
if(this.Reset||(this.bs_header_flag&&this.just_seeked)) {
int rt = calc_sbr_tables(this.bs_start_freq, this.bs_stop_freq,
this.bs_samplerate_mode, this.bs_freq_scale,
this.bs_alter_scale, this.bs_xover_band);
/* if an error occured with the new header values revert to the old ones */
if(rt>0) {
calc_sbr_tables(saved_start_freq, saved_stop_freq,
saved_samplerate_mode, saved_freq_scale,
saved_alter_scale, saved_xover_band);
}
}
if(result==0) {
result = sbr_data(ld);
/* sbr_data() returning an error means that there was an error in
envelope_time_border_vector().
In this case the old time border vector is saved and all the previous
data normally read after sbr_grid() is saved.
*/
/* to be on the safe side, calculate old sbr tables in case of error */
if((result>0)
&&(this.Reset||(this.bs_header_flag&&this.just_seeked))) {
calc_sbr_tables(saved_start_freq, saved_stop_freq,
saved_samplerate_mode, saved_freq_scale,
saved_alter_scale, saved_xover_band);
}
/* we should be able to safely set result to 0 now, */
/* but practise indicates this doesn't work well */
}
}
else {
result = 1;
}
num_sbr_bits2 = (int) (ld.getPosition()-num_sbr_bits1);
/* check if we read more bits then were available for sbr */
if(8*cnt7) {
ld.readBits(8);
num_align_bits -= 8;
}
ld.readBits(num_align_bits);
}
return result;
}
/* table 3 */
private void sbr_header(IBitStream ld) throws AACException {
boolean bs_header_extra_1, bs_header_extra_2;
this.header_count++;
this.bs_amp_res = ld.readBool();
/* bs_start_freq and bs_stop_freq must define a fequency band that does
not exceed 48 channels */
this.bs_start_freq = ld.readBits(4);
this.bs_stop_freq = ld.readBits(4);
this.bs_xover_band = ld.readBits(3);
ld.readBits(2); //reserved
bs_header_extra_1 = ld.readBool();
bs_header_extra_2 = ld.readBool();
if(bs_header_extra_1) {
this.bs_freq_scale = ld.readBits(2);
this.bs_alter_scale = ld.readBool();
this.bs_noise_bands = ld.readBits(2);
}
else {
/* Default values */
this.bs_freq_scale = 2;
this.bs_alter_scale = true;
this.bs_noise_bands = 2;
}
if(bs_header_extra_2) {
this.bs_limiter_bands = ld.readBits(2);
this.bs_limiter_gains = ld.readBits(2);
this.bs_interpol_freq = ld.readBool();
this.bs_smoothing_mode = ld.readBool();
}
else {
/* Default values */
this.bs_limiter_bands = 2;
this.bs_limiter_gains = 2;
this.bs_interpol_freq = true;
this.bs_smoothing_mode = true;
}
}
/* table 4 */
private int sbr_data(IBitStream ld) throws AACException {
int result;
this.rate = (this.bs_samplerate_mode!=0) ? 2 : 1;
if(stereo) {
if((result = sbr_channel_pair_element(ld))>0)
return result;
}
else {
if((result = sbr_single_channel_element(ld))>0)
return result;
}
return 0;
}
/* table 5 */
private int sbr_single_channel_element(IBitStream ld) throws AACException {
int result;
if(ld.readBool()) {
ld.readBits(4); //reserved
}
if((result = sbr_grid(ld, 0))>0)
return result;
sbr_dtdf(ld, 0);
invf_mode(ld, 0);
sbr_envelope(ld, 0);
sbr_noise(ld, 0);
NoiseEnvelope.dequantChannel(this, 0);
Arrays.fill(bs_add_harmonic[0], 0, 64, 0);
Arrays.fill(bs_add_harmonic[1], 0, 64, 0);
this.bs_add_harmonic_flag[0] = ld.readBool();
if(this.bs_add_harmonic_flag[0])
sinusoidal_coding(ld, 0);
this.bs_extended_data = ld.readBool();
if(this.bs_extended_data) {
int nr_bits_left;
int ps_ext_read = 0;
int cnt = ld.readBits(4);
if(cnt==15) {
cnt += ld.readBits(8);
}
nr_bits_left = 8*cnt;
while(nr_bits_left>7) {
int tmp_nr_bits = 0;
this.bs_extension_id = ld.readBits(2);
tmp_nr_bits += 2;
/* allow only 1 PS extension element per extension data */
if(this.bs_extension_id==EXTENSION_ID_PS) {
if(ps_ext_read==0) {
ps_ext_read = 1;
}
else {
/* to be safe make it 3, will switch to "default"
* in sbr_extension() */
this.bs_extension_id = 3;
}
}
tmp_nr_bits += sbr_extension(ld, this.bs_extension_id, nr_bits_left);
/* check if the data read is bigger than the number of available bits */
if(tmp_nr_bits>nr_bits_left)
return 1;
nr_bits_left -= tmp_nr_bits;
}
/* Corrigendum */
if(nr_bits_left>0) {
ld.readBits(nr_bits_left);
}
}
return 0;
}
/* table 6 */
private int sbr_channel_pair_element(IBitStream ld) throws AACException {
int n, result;
if(ld.readBool()) {
//reserved
ld.readBits(4);
ld.readBits(4);
}
this.bs_coupling = ld.readBool();
if(this.bs_coupling) {
if((result = sbr_grid(ld, 0))>0)
return result;
/* need to copy some data from left to right */
this.bs_frame_class[1] = this.bs_frame_class[0];
this.L_E[1] = this.L_E[0];
this.L_Q[1] = this.L_Q[0];
this.bs_pointer[1] = this.bs_pointer[0];
for(n = 0; n<=this.L_E[0]; n++) {
this.t_E[1][n] = this.t_E[0][n];
this.f[1][n] = this.f[0][n];
}
for(n = 0; n<=this.L_Q[0]; n++) {
this.t_Q[1][n] = this.t_Q[0][n];
}
sbr_dtdf(ld, 0);
sbr_dtdf(ld, 1);
invf_mode(ld, 0);
/* more copying */
for(n = 0; n0)
return result;
if((result = sbr_grid(ld, 1))>0) {
/* restore first channel data as well */
this.bs_frame_class[0] = saved_frame_class;
this.L_E[0] = saved_L_E;
this.L_Q[0] = saved_L_Q;
for(n = 0; n<6; n++) {
this.t_E[0][n] = saved_t_E[n];
}
for(n = 0; n<3; n++) {
this.t_Q[0][n] = saved_t_Q[n];
}
return result;
}
sbr_dtdf(ld, 0);
sbr_dtdf(ld, 1);
invf_mode(ld, 0);
invf_mode(ld, 1);
sbr_envelope(ld, 0);
sbr_envelope(ld, 1);
sbr_noise(ld, 0);
sbr_noise(ld, 1);
Arrays.fill(bs_add_harmonic[0], 0, 64, 0);
Arrays.fill(bs_add_harmonic[1], 0, 64, 0);
this.bs_add_harmonic_flag[0] = ld.readBool();
if(this.bs_add_harmonic_flag[0])
sinusoidal_coding(ld, 0);
this.bs_add_harmonic_flag[1] = ld.readBool();
if(this.bs_add_harmonic_flag[1])
sinusoidal_coding(ld, 1);
}
NoiseEnvelope.dequantChannel(this, 0);
NoiseEnvelope.dequantChannel(this, 1);
if(this.bs_coupling)
NoiseEnvelope.unmap(this);
this.bs_extended_data = ld.readBool();
if(this.bs_extended_data) {
int nr_bits_left;
int cnt = ld.readBits(4);
if(cnt==15) {
cnt += ld.readBits(8);
}
nr_bits_left = 8*cnt;
while(nr_bits_left>7) {
int tmp_nr_bits = 0;
this.bs_extension_id = ld.readBits(2);
tmp_nr_bits += 2;
tmp_nr_bits += sbr_extension(ld, this.bs_extension_id, nr_bits_left);
/* check if the data read is bigger than the number of available bits */
if(tmp_nr_bits>nr_bits_left)
return 1;
nr_bits_left -= tmp_nr_bits;
}
/* Corrigendum */
if(nr_bits_left>0) {
ld.readBits(nr_bits_left);
}
}
return 0;
}
/* integer log[2](x): input range [0,10) */
private int sbr_log2(int val) {
int log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3, 4};
if(val<10&&val>=0)
return log2tab[val];
else
return 0;
}
/* table 7 */
private int sbr_grid(IBitStream ld, int ch) throws AACException {
int i, env, rel, result;
int bs_abs_bord, bs_abs_bord_1;
int bs_num_env = 0;
int saved_L_E = this.L_E[ch];
int saved_L_Q = this.L_Q[ch];
int saved_frame_class = this.bs_frame_class[ch];
this.bs_frame_class[ch] = ld.readBits(2);
switch(this.bs_frame_class[ch]) {
case FIXFIX:
i = ld.readBits(2);
bs_num_env = Math.min(1<1)
this.L_Q[ch] = 2;
else
this.L_Q[ch] = 1;
/* TODO: this code can probably be integrated into the code above! */
if((result = TFGrid.envelope_time_border_vector(this, ch))>0) {
this.bs_frame_class[ch] = saved_frame_class;
this.L_E[ch] = saved_L_E;
this.L_Q[ch] = saved_L_Q;
return result;
}
TFGrid.noise_floor_time_border_vector(this, ch);
return 0;
}
/* table 8 */
private void sbr_dtdf(IBitStream ld, int ch) throws AACException {
int i;
for(i = 0; i=0) {
bit = ld.readBit();
index = t_huff[index][bit];
}
return index+64;
}
private int sbr_save_prev_data(int ch) {
int i;
/* save data for next frame */
this.kx_prev = this.kx;
this.M_prev = this.M;
this.bsco_prev = this.bsco;
this.L_E_prev[ch] = this.L_E[ch];
/* sbr.L_E[ch] can become 0 on files with bit errors */
if(this.L_E[ch]<=0)
return 19;
this.f_prev[ch] = this.f[ch][this.L_E[ch]-1];
for(i = 0; i0) {
dont_process = true;
}
}
if(this.just_seeked||dont_process) {
for(l = 0; l
© 2015 - 2025 Weber Informatics LLC | Privacy Policy