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

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

There is a newer version: 0.2.5
Show newest version
package net.sourceforge.jaad.aac.sbr;
import static java.lang.System.arraycopy;

/**
 * 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
 */
class HFAdjustment implements SBRConstants, NoiseTable {

	private static final float[] h_smooth = {
		0.03183050093751f, 0.11516383427084f,
		0.21816949906249f, 0.30150283239582f,
		0.33333333333333f
	};
	private static final int[] phi_re = {1, 0, -1, 0};
	private static final int[] phi_im = {0, 1, 0, -1};
	private static final float[] limGain = {0.5f, 1.0f, 2.0f, 1e10f};
	private static final float EPS = 1e-12f;
	private float[][] G_lim_boost;
	private float[][] Q_M_lim_boost;
	private float[][] S_M_boost;

	public HFAdjustment() {
	    this.G_lim_boost = new float[MAX_L_E][MAX_M];
	    this.Q_M_lim_boost = new float[MAX_L_E][MAX_M];
	    this.S_M_boost = new float[MAX_L_E][MAX_M];
    }
	
	public static int hf_adjustment(SBR sbr, float[][][] Xsbr, int ch) {
		HFAdjustment adj = new HFAdjustment();
		int ret = 0;

		if(sbr.bs_frame_class[ch]==FIXFIX) {
			sbr.l_A[ch] = -1;
		}
		else if(sbr.bs_frame_class[ch]==VARFIX) {
			if(sbr.bs_pointer[ch]>1)
				sbr.l_A[ch] = sbr.bs_pointer[ch]-1;
			else
				sbr.l_A[ch] = -1;
		}
		else {
			if(sbr.bs_pointer[ch]==0)
				sbr.l_A[ch] = -1;
			else
				sbr.l_A[ch] = sbr.L_E[ch]+1-sbr.bs_pointer[ch];
		}

		ret = estimate_current_envelope(sbr, adj, Xsbr, ch);
		if(ret>0) return 1;

		calculate_gain(sbr, adj, ch);

		hf_assembly(sbr, adj, Xsbr, ch);

		return 0;
	}

	private static int get_S_mapped(SBR sbr, int ch, int l, int current_band) {
		if(sbr.f[ch][l]==HI_RES) {
			/* in case of using f_table_high we just have 1 to 1 mapping
			 * from bs_add_harmonic[l][k]
			 */
			if((l>=sbr.l_A[ch])
				||(sbr.bs_add_harmonic_prev[ch][current_band]!=0&&sbr.bs_add_harmonic_flag_prev[ch])) {
				return sbr.bs_add_harmonic[ch][current_band];
			}
		}
		else {
			int b, lb, ub;

			/* in case of f_table_low we check if any of the HI_RES bands
			 * within this LO_RES band has bs_add_harmonic[l][k] turned on
			 * (note that borders in the LO_RES table are also present in
			 * the HI_RES table)
			 */

			/* find first HI_RES band in current LO_RES band */
			lb = 2*current_band-((sbr.N_high&1)!=0 ? 1 : 0);
			/* find first HI_RES band in next LO_RES band */
			ub = 2*(current_band+1)-((sbr.N_high&1)!=0 ? 1 : 0);

			/* check all HI_RES bands in current LO_RES band for sinusoid */
			for(b = lb; b=sbr.l_A[ch])
					||(sbr.bs_add_harmonic_prev[ch][b]!=0&&sbr.bs_add_harmonic_flag_prev[ch])) {
					if(sbr.bs_add_harmonic[ch][b]==1)
						return 1;
				}
			}
		}

		return 0;
	}

	private static int estimate_current_envelope(SBR sbr, HFAdjustment adj,
		float[][][] Xsbr, int ch) {
		int m, l, j, k, k_l, k_h, p;
		float nrg, div;

		if(sbr.bs_interpol_freq) {
			for(l = 0; l=5)
								ri -= 5;
							G_filt += (sbr.G_temp_prev[ch][ri][m]*curr_h_smooth);
							Q_filt += (sbr.Q_temp_prev[ch][ri][m]*curr_h_smooth);
						}
					}
					else {
						G_filt = sbr.G_temp_prev[ch][sbr.GQ_ringbuf_index[ch]][m];
						Q_filt = sbr.Q_temp_prev[ch][sbr.GQ_ringbuf_index[ch]][m];
					}

					Q_filt = (adj.S_M_boost[l][m]!=0||no_noise) ? 0 : Q_filt;

					/* add noise to the output */
					fIndexNoise = (fIndexNoise+1)&511;

					/* the smoothed gain values are applied to Xsbr */
					/* V is defined, not calculated */
					Xsbr[i+sbr.tHFAdj][m+sbr.kx][0] = G_filt*Xsbr[i+sbr.tHFAdj][m+sbr.kx][0]
						+(Q_filt*NOISE_TABLE[fIndexNoise][0]);
					if(sbr.bs_extension_id==3&&sbr.bs_extension_data==42)
						Xsbr[i+sbr.tHFAdj][m+sbr.kx][0] = 16428320;
					Xsbr[i+sbr.tHFAdj][m+sbr.kx][1] = G_filt*Xsbr[i+sbr.tHFAdj][m+sbr.kx][1]
						+(Q_filt*NOISE_TABLE[fIndexNoise][1]);

					{
						int rev = (((m+sbr.kx)&1)!=0 ? -1 : 1);
						psi[0] = adj.S_M_boost[l][m]*phi_re[fIndexSine];
						Xsbr[i+sbr.tHFAdj][m+sbr.kx][0] += psi[0];

						psi[1] = rev*adj.S_M_boost[l][m]*phi_im[fIndexSine];
						Xsbr[i+sbr.tHFAdj][m+sbr.kx][1] += psi[1];
					}
				}

				fIndexSine = (fIndexSine+1)&3;

				/* update the ringbuffer index used for filtering G and Q with h_smooth */
				sbr.GQ_ringbuf_index[ch]++;
				if(sbr.GQ_ringbuf_index[ch]>=5)
					sbr.GQ_ringbuf_index[ch] = 0;
			}
		}

		sbr.index_noise_prev[ch] = fIndexNoise;
		sbr.psi_is_prev[ch] = fIndexSine;
	}

	private static void calculate_gain(SBR sbr, HFAdjustment adj, int ch) {
		int m, l, k;

		int current_t_noise_band = 0;
		int S_mapped;

		float[] Q_M_lim = new float[MAX_M];
		float[] G_lim = new float[MAX_M];
		float G_boost;
		float[] S_M = new float[MAX_M];

		for(l = 0; lsbr.t_Q[ch][current_t_noise_band+1]) {
				current_t_noise_band++;
			}

			for(k = 0; k=sbr.l_A[ch])
						||(sbr.bs_add_harmonic_prev[ch][current_hi_res_band]!=0&&sbr.bs_add_harmonic_flag_prev[ch])) {
						/* find the middle subband of the HI_RES frequency band */
						if((m+sbr.kx)==(sbr.f_table_res[HI_RES][current_hi_res_band+1]+sbr.f_table_res[HI_RES][current_hi_res_band])>>1)
							S_index_mapped = sbr.bs_add_harmonic[ch][current_hi_res_band];
					}


					/* Q_div: [0..1] (1/(1+Q_mapped)) */
					Q_div = sbr.Q_div[ch][current_f_noise_band][current_t_noise_band];


					/* Q_div2: [0..1] (Q_mapped/(1+Q_mapped)) */
					Q_div2 = sbr.Q_div2[ch][current_f_noise_band][current_t_noise_band];


					/* Q_M only depends on E_orig and Q_div2:
					 * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on
					 * a change of current noise band
					 */
					Q_M = sbr.E_orig[ch][current_res_band2][l]*Q_div2;


					/* S_M only depends on E_orig, Q_div and S_index_mapped:
					 * S_index_mapped can only be non-zero once per HI_RES band
					 */
					if(S_index_mapped==0) {
						S_M[m] = 0;
					}
					else {
						S_M[m] = sbr.E_orig[ch][current_res_band2][l]*Q_div;

						/* accumulate sinusoid part of the total energy */
						den += S_M[m];
					}


					/* calculate gain */
					/* ratio of the energy of the original signal and the energy
					 * of the HF generated signal
					 */
					G = sbr.E_orig[ch][current_res_band2][l]/(1.0f+sbr.E_curr[ch][m][l]);
					if((S_mapped==0)&&(delta==1))
						G *= Q_div;
					else if(S_mapped==1)
						G *= Q_div2;


					/* limit the additional noise energy level */
					/* and apply the limiter */
					if(G_max>G) {
						Q_M_lim[m] = Q_M;
						G_lim[m] = G;
					}
					else {
						Q_M_lim[m] = Q_M*G_max/G;
						G_lim[m] = G_max;
					}


					/* accumulate the total energy */
					den += sbr.E_curr[ch][m][l]*G_lim[m];
					if((S_index_mapped==0)&&(l!=sbr.l_A[ch]))
						den += Q_M_lim[m];
				}

				/* G_boost: [0..2.51188643] */
				G_boost = (acc1+EPS)/(den+EPS);
				G_boost = Math.min(G_boost, 2.51188643f /* 1.584893192 ^ 2 */);

				for(m = ml1; m




© 2015 - 2024 Weber Informatics LLC | Privacy Policy