All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.jaad.aac.sbr.SBR Maven / Gradle / Ivy

There is a newer version: 0.2.5
Show newest version
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 - 2024 Weber Informatics LLC | Privacy Policy