ref: 708eea7d2978b554421e6f485ce237430cfeed80
dir: /psych.c/
/* * Psychoacoustics * * Copyright (c) 1999 M. Bakker * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /************************************************************************** Version Control Information Method: CVS Identifiers: $Revision: 1.69 $ $Date: 2000/10/06 14:47:27 $ (check in) $Author: menno $ *************************************************************************/ #include <math.h> #include <memory.h> #include "psych.h" #include "transfo.h" double sqrt2048, sqrt256; SR_INFO sr_info_aac[MAX_SAMPLING_RATES+1] = { { 8000, 40, 15, { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, 28, 32, 32, 36, 40, 44, 48, 52, 56, 60, 64, 80 }, { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 20 } }, { 11025, 43, 15, { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64 }, { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 } }, { 12000, 43, 15, { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64 }, { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 } }, { 16000, 43, 15, { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64 }, { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 } }, { 22050, 47, 15, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64 }, { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 16, 20 } },{ 24000, 47, 15, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64 }, { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 16, 20 } }, { 32000, 51, 14, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 },{ 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 } }, { 44100, 49, 14, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96 }, { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 } }, { 48000, 49, 14, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96 }, { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 } }, {64000, 47, 12, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 36, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 },{ 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 32 } }, { 88200, 41, 12, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 },{ 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 } }, { 96000, 41, 12, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 },{ 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 } }, { -1 } }; double sample[MAX_TIME_CHANNELS*2][BLOCK_LEN_LONG*2]; /* sample value */ FFT_TABLE_LONG fft_tbl_long; /* table for long fft */ FFT_TABLE_SHORT fft_tbl_short; /* table for short fft */ PARTITION_TABLE_LONG part_tbl_long; PARTITION_TABLE_SHORT part_tbl_short; DYN_PART_TABLE_LONG dyn_long; DYN_PART_TABLE_SHORT dyn_short; PSY_STATVARIABLE_LONG psy_stvar_long[MAX_TIME_CHANNELS*2]; /* variables for long block */ PSY_STATVARIABLE_SHORT psy_stvar_short[MAX_TIME_CHANNELS*2]; /* variables for short block */ void EncTf_psycho_acoustic_init( void ) { int chanNum; psy_fft_table_init(&fft_tbl_long, &fft_tbl_short); /* initializing fft table */ for (chanNum=0;chanNum<MAX_TIME_CHANNELS*2;chanNum++) { psy_calc_init(&sample[chanNum], &psy_stvar_long[chanNum], &psy_stvar_short[chanNum]); /* initializing static variables */ } } void psy_fft_table_init(FFT_TABLE_LONG *fft_tbl_long, FFT_TABLE_SHORT *fft_tbl_short ) { int i; /* generating Hann window */ for(i = 0; i < BLOCK_LEN_LONG*2; i++) fft_tbl_long->hw[i] = 0.5 * (1-cos(2.0*M_PI*(i+0.5)/(BLOCK_LEN_LONG*2))); for(i = 0; i < BLOCK_LEN_SHORT*2; i++) fft_tbl_short->hw[i] = 0.5 * (1-cos(2.0*M_PI*(i+0.5)/(BLOCK_LEN_SHORT*2))); } /* * This Function calculates the Frequency in Hertz given a * Bark-value. It uses the Traunmueller-formula for bark>2 * and a linear inerpolation below. * KAF */ double bark2hz (double bark) { double hz; if(bark>2.0) hz = 1960 / (26.81 / (bark + 0.53) - 1); else hz = bark * 102.9; return (hz); } /* * This Function calculates the Frequency in Bark given a * Frequency-value in Hertz. It uses the Traunmueller-formula * for frequency>200Hz and a linear inerpolation below. * KAF */ double hz2bark (double hz) { double bark; if(hz>200.0) bark = 26.81 / (1 + (1960 / hz)) - 0.53; else bark = hz / 102.9; return (bark); } void psy_part_table_init(double sampling_rate, PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short ) { int b,bb; double tmp; int cbands, prev_cbound, crit_bands, cbound; cbands = (int)hz2bark(sampling_rate/2.0) + 1; cbands *= 3; part_tbl_long->sampling_rate = (int)sampling_rate; part_tbl_long->w_low[0] = 0; part_tbl_long->w_high[0] = 1; part_tbl_long->width[0] = 1; prev_cbound = 0; crit_bands = 0; for(b = 1; b <= cbands; b++) { cbound = (int)(bark2hz((double)b/3) * (double)BLOCK_LEN_LONG * 2.0 / sampling_rate + 0.5); if(cbound > prev_cbound) { crit_bands++; part_tbl_long->w_low[crit_bands] = min(prev_cbound,BLOCK_LEN_LONG-1); part_tbl_long->w_high[crit_bands] = min(cbound,BLOCK_LEN_LONG); part_tbl_long->width[crit_bands] = part_tbl_long->w_high[crit_bands] - part_tbl_long->w_low[crit_bands]; prev_cbound = cbound; if (part_tbl_long->w_high[crit_bands] == BLOCK_LEN_LONG) break; } } part_tbl_long->len = crit_bands+1; // printf("%d %d\t",part_tbl_long->len, part_tbl_long->w_high[crit_bands]); cbands /= 3; part_tbl_short->sampling_rate = (int)sampling_rate; part_tbl_short->w_low[0] = 0; part_tbl_short->w_high[0] = 1; part_tbl_short->width[0] = 1; prev_cbound = 0; crit_bands = 0; for(b = 1; b <= cbands; b++) { cbound = (int)(bark2hz((double)b/*/3*/) * (double)BLOCK_LEN_SHORT * 2.0 / sampling_rate +0.5); if(cbound > prev_cbound) { crit_bands++; part_tbl_short->w_low[crit_bands] = min(prev_cbound,BLOCK_LEN_SHORT-1); part_tbl_short->w_high[crit_bands] = min(cbound,BLOCK_LEN_SHORT); part_tbl_short->width[crit_bands] = part_tbl_short->w_high[crit_bands] - part_tbl_short->w_low[crit_bands]; prev_cbound = cbound; if (part_tbl_short->w_high[crit_bands] == BLOCK_LEN_SHORT) break; } } part_tbl_short->len = crit_bands+1; // printf("%d %d\n",part_tbl_short->len, part_tbl_short->w_high[crit_bands]); // Using Traunmuller formula for bark, for more info see: // http://www.ling.su.se/staff/hartmut/bark.htm for(b = 0; b < part_tbl_long->len; b++) { double ji = part_tbl_long->w_low[b] + (part_tbl_long->width[b]-1)/2.0; double freq = part_tbl_long->sampling_rate*ji/2048; double bark = 26.81/(1+(1960/freq)) - 0.53; dyn_long.bval[b] = bark; } for(b = 0; b < part_tbl_short->len ; b++) { double ji = part_tbl_short->w_low[b] + (part_tbl_short->width[b]-1)/2.0; double freq = part_tbl_short->sampling_rate*ji/256; double bark = 26.81/(1+(1960/freq)) - 0.53; dyn_short.bval[b]=bark; } // Calculate the spreading function { double tmpx,tmpy,tmp,x,b1,b2; int b, bb; for( b = 0; b < part_tbl_long->len; b++) { b2 = dyn_long.bval[b]; for( bb = 0; bb < part_tbl_long->len; bb++) { b1 = dyn_long.bval[bb]; if (b>=bb) tmpx = (b2 - b1)*3.0; else tmpx = (b2 - b1)*1.5; if(tmpx>=0.5 && tmpx<=2.5) { tmp = tmpx - 0.5; x = 8.0 * (tmp*tmp - 2.0 * tmp); } else x = 0.0; tmpx += 0.474; tmpy = 15.811389 + 7.5*tmpx - 17.5*sqrt(1.0+tmpx*tmpx); if (tmpy <= -60.0) dyn_long.spreading[b][bb] = 0.0; else dyn_long.spreading[b][bb] = exp( (x + tmpy)*0.2302585093 ); } } for( b = 0; b < part_tbl_short->len; b++) { b2 = dyn_short.bval[b]; for( bb = 0; bb < part_tbl_short->len; bb++) { b1 = dyn_short.bval[bb]; if (b>=bb) tmpx = (b2 - b1)*3.0; else tmpx = (b2 - b1)*1.5; if(tmpx>=0.5 && tmpx<=2.5) { tmp = tmpx - 0.5; x = 8.0 * (tmp*tmp - 2.0 * tmp); } else x = 0.0; tmpx += 0.474; tmpy = 15.811389 + 7.5*tmpx - 17.5*sqrt(1.0+tmpx*tmpx); if (tmpy <= -60.0) dyn_short.spreading[b][bb] = 0.0; else dyn_short.spreading[b][bb] = exp( (x + tmpy)*0.2302585093 ); } } } for( b = 0; b < part_tbl_long->len; b++){ tmp = 0.0; for( bb = 0; bb < part_tbl_long->len; bb++) tmp += dyn_long.spreading[bb][b]; dyn_long.rnorm[b] = 1.0/tmp; } for( b = 0; b < part_tbl_short->len; b++){ tmp = 0.0; for( bb = 0; bb < part_tbl_short->len; bb++) tmp += dyn_short.spreading[bb][b]; dyn_short.rnorm[b] = 1.0/tmp; } for(b = 0; b < part_tbl_long->len; b++) { dyn_long.bmax[b] = pow(10, 1.25*(1-cos(M_PI*b/part_tbl_long->len))-2.5); // dyn_long.bmax[b] = pow(10, -3*(0.5+0.5*(M_PI*(min(dyn_long.bval[b], 15.5)/15.5)))); } for(b = 0; b < part_tbl_short->len; b++) { dyn_short.bmax[b] = pow(10, 1.25*(1-cos(M_PI*b/part_tbl_short->len))-2.5); // dyn_short.bmax[b] = pow(10, -3*(0.5+0.5*(M_PI*(min(dyn_short.bval[b], 15.5)/15.5)))); } part_tbl_long->dyn = &dyn_long; part_tbl_short->dyn = &dyn_short; } void psy_calc_init( double sample[][BLOCK_LEN_LONG*2], PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short ) { int ch = 0; int i; for(i = 0; i < BLOCK_LEN_LONG*2; i++){ sample[ch][i] = 0.0; } for(i = 0; i < BLOCK_LEN_LONG*3; i++){ psy_stvar_long->fft_r[i] = 0.0; psy_stvar_long->fft_f[i] = 0.0; } psy_stvar_long->p_fft = 0; for(i = 0; i < NPART_LONG*2; i++){ psy_stvar_long->nb[i] = 90.0; } psy_stvar_long->p_nb = NPART_LONG; for(i = 0; i < BLOCK_LEN_SHORT; i++) { psy_stvar_short->last6_fft_r[i] = 0.0; psy_stvar_short->last6_fft_f[i] = 0.0; psy_stvar_short->last7_fft_r[i] = 0.0; psy_stvar_short->last7_fft_f[i] = 0.0; } for(i = 0; i < NPART_SHORT; i++){ psy_stvar_short->last7_nb[i] = 90.0; } sqrt2048 = 1/sqrt(2048); sqrt256 = 1/sqrt(256); } void psy_fill_lookahead(double *p_time_signal[], int no_of_chan) { int i, ch; for (ch = 0; ch < no_of_chan; ch++) { for(i = 0; i < BLOCK_LEN_LONG; i++){ sample[ch][i+BLOCK_LEN_LONG] = p_time_signal[ch][i]; } } } /* main */ void EncTf_psycho_acoustic( /* input */ double sampling_rate, int no_of_chan, /* no of audio channels */ Ch_Info* channelInfo, double *p_time_signal[], enum WINDOW_TYPE block_type[], int use_MS, /* output */ CH_PSYCH_OUTPUT_LONG p_chpo_long[], CH_PSYCH_OUTPUT_SHORT p_chpo_short[][MAX_SHORT_WINDOWS] ) { int chanNum, i; SR_INFO *p_sri; static int flag = 0; PSY_VARIABLE_LONG psy_var_long[4]; /* variables for long block */ PSY_VARIABLE_SHORT psy_var_short[4]; /* variables for short block */ memset(&psy_var_long, 0, sizeof(psy_var_long)); memset(&psy_var_short, 0, sizeof(psy_var_short)); p_sri = &sr_info_aac[0]; /* find correct sampling rate depending parameters */ while( p_sri->sampling_rate != (long)sampling_rate ) { p_sri++; } if( flag==0 ) { psy_part_table_init(sampling_rate, &part_tbl_long, &part_tbl_short); /* initializing Table B 2.1.*.a, B 2.1.*.b in N1650 */ flag = 1; } for (chanNum = 0; chanNum < no_of_chan; chanNum++) { if (channelInfo[chanNum].present) { if ((channelInfo[chanNum].cpe) && (channelInfo[chanNum].ch_is_left)) { /* CPE */ int leftChan = chanNum; int rightChan = channelInfo[chanNum].paired_ch; int midChan = chanNum + MAX_TIME_CHANNELS; int sideChan = chanNum + MAX_TIME_CHANNELS; psy_step1(p_time_signal, sample, leftChan); psy_step1(p_time_signal, sample, rightChan); psy_step2(sample, &psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &fft_tbl_long, &fft_tbl_short, leftChan); psy_step2(sample, &psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &fft_tbl_long, &fft_tbl_short, rightChan); if (use_MS == 0) psy_step2MS(psy_stvar_long, psy_stvar_short, leftChan, rightChan, midChan, sideChan); psy_step3(&psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &psy_var_long[0], &psy_var_short[0]); psy_step3(&psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &psy_var_long[1], &psy_var_short[1]); psy_step4(&psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &psy_var_long[0], &psy_var_short[0]); psy_step4(&psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) psy_step4MS(psy_var_long, psy_var_short, 0, 1, 2, 3); psy_step5(&part_tbl_long, &part_tbl_short, &psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &psy_var_long[0], &psy_var_short[0]); psy_step5(&part_tbl_long, &part_tbl_short, &psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) { psy_step5(&part_tbl_long, &part_tbl_short, &psy_stvar_long[midChan], &psy_stvar_short[midChan], &psy_var_long[2], &psy_var_short[2]); psy_step5(&part_tbl_long, &part_tbl_short, &psy_stvar_long[sideChan], &psy_stvar_short[sideChan], &psy_var_long[3], &psy_var_short[3]); } psy_step6(&part_tbl_long, &part_tbl_short, &psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &psy_var_long[0], &psy_var_short[0]); psy_step6(&part_tbl_long, &part_tbl_short, &psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) { psy_step6(&part_tbl_long, &part_tbl_short, &psy_stvar_long[midChan], &psy_stvar_short[midChan], &psy_var_long[2], &psy_var_short[2]); psy_step6(&part_tbl_long, &part_tbl_short, &psy_stvar_long[sideChan], &psy_stvar_short[sideChan], &psy_var_long[3], &psy_var_short[3]); } psy_step7(&part_tbl_long, &part_tbl_short, &psy_var_long[0], &psy_var_short[0]); psy_step7(&part_tbl_long, &part_tbl_short, &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) { psy_step7MS(psy_var_long, psy_var_short, 0, 1, 2, 3); } psy_step8(&part_tbl_long, &part_tbl_short, &psy_var_long[0], &psy_var_short[0]); psy_step8(&part_tbl_long, &part_tbl_short, &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) { psy_step8(&part_tbl_long, &part_tbl_short, &psy_var_long[2], &psy_var_short[2]); psy_step8(&part_tbl_long, &part_tbl_short, &psy_var_long[3], &psy_var_short[3]); } psy_step9(&part_tbl_long, &part_tbl_short, &psy_var_long[0], &psy_var_short[0]); psy_step9(&part_tbl_long, &part_tbl_short, &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) { psy_step9(&part_tbl_long, &part_tbl_short, &psy_var_long[2], &psy_var_short[2]); psy_step9(&part_tbl_long, &part_tbl_short, &psy_var_long[3], &psy_var_short[3]); } psy_step10(&part_tbl_long, &part_tbl_short, &psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &psy_var_long[0], &psy_var_short[0]); psy_step10(&part_tbl_long, &part_tbl_short, &psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) { psy_step10(&part_tbl_long, &part_tbl_short, &psy_stvar_long[midChan], &psy_stvar_short[midChan], &psy_var_long[2], &psy_var_short[2]); psy_step10(&part_tbl_long, &part_tbl_short, &psy_stvar_long[sideChan], &psy_stvar_short[sideChan], &psy_var_long[3], &psy_var_short[3]); psy_step11MS(&part_tbl_long, &part_tbl_short, psy_stvar_long, psy_stvar_short, leftChan, rightChan, midChan, sideChan); } psy_step11(&part_tbl_long, &part_tbl_short, &psy_stvar_long[leftChan], &psy_stvar_short[leftChan]); psy_step11(&part_tbl_long, &part_tbl_short, &psy_stvar_long[rightChan], &psy_stvar_short[rightChan]); if (use_MS == 0) { psy_step11(&part_tbl_long, &part_tbl_short, &psy_stvar_long[midChan], &psy_stvar_short[midChan]); psy_step11(&part_tbl_long, &part_tbl_short, &psy_stvar_long[sideChan], &psy_stvar_short[sideChan]); } psy_step12(&part_tbl_long, &part_tbl_short, &psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &psy_var_long[0], &psy_var_short[0]); psy_step12(&part_tbl_long, &part_tbl_short, &psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &psy_var_long[1], &psy_var_short[1]); psy_step13(&psy_var_long[0], &block_type[leftChan]); if (*block_type != ONLY_SHORT_WINDOW) { psy_step13(&psy_var_long[1], &block_type[rightChan]); block_type[leftChan] = block_type[rightChan]; } else { block_type[rightChan] = block_type[leftChan]; } psy_step14(p_sri, &part_tbl_long, &part_tbl_short, &psy_stvar_long[leftChan], &psy_stvar_short[leftChan], &psy_var_long[0], &psy_var_short[0]); psy_step14(p_sri, &part_tbl_long, &part_tbl_short, &psy_stvar_long[rightChan], &psy_stvar_short[rightChan], &psy_var_long[1], &psy_var_short[1]); if (use_MS == 0) { psy_step14(p_sri, &part_tbl_long, &part_tbl_short, &psy_stvar_long[midChan], &psy_stvar_short[midChan], &psy_var_long[2], &psy_var_short[2]); psy_step14(p_sri, &part_tbl_long, &part_tbl_short, &psy_stvar_long[sideChan], &psy_stvar_short[sideChan], &psy_var_long[3], &psy_var_short[3]); psy_step15(p_sri, psy_stvar_long, psy_stvar_short, psy_var_long, psy_var_short, leftChan, rightChan, midChan, sideChan); } p_chpo_long[leftChan].p_ratio = psy_stvar_long[leftChan].ismr; p_chpo_long[rightChan].p_ratio = psy_stvar_long[rightChan].ismr; p_chpo_long[leftChan].cb_width = p_sri->cb_width_long; p_chpo_long[rightChan].cb_width = p_sri->cb_width_long; p_chpo_long[leftChan].no_of_cb = p_sri->num_cb_long; p_chpo_long[rightChan].no_of_cb = p_sri->num_cb_long; memcpy(p_chpo_long[rightChan].use_ms, psy_stvar_long[rightChan].use_ms, NSFB_LONG*sizeof(int)); for( i=0; i<MAX_SHORT_WINDOWS; i++ ) { p_chpo_short[leftChan][i].p_ratio = psy_stvar_short[leftChan].ismr[i]; p_chpo_short[rightChan][i].p_ratio = psy_stvar_short[rightChan].ismr[i]; p_chpo_short[leftChan][i].cb_width = p_sri->cb_width_short; p_chpo_short[rightChan][i].cb_width = p_sri->cb_width_short; p_chpo_short[leftChan][i].no_of_cb = p_sri->num_cb_short; p_chpo_short[rightChan][i].no_of_cb = p_sri->num_cb_short; memcpy(p_chpo_short[rightChan][i].use_ms, psy_stvar_short[rightChan].use_ms[i], NSFB_SHORT*sizeof(int)); } } else if (channelInfo[chanNum].lfe) { /* LFE */ // LFE psych ratios are set to -24 dB for low frequencies for (i = 0; i < 10; i++) { psy_stvar_long[chanNum].ismr[i] = 0.004; /* -24 dB */ } for (i = 10; i < NSFB_LONG; i++) { psy_stvar_long[chanNum].ismr[i] = 1.0; } p_chpo_long[chanNum].p_ratio = psy_stvar_long[chanNum].ismr; block_type[chanNum] = ONLY_LONG_WINDOW; // set the scalefactor band values p_chpo_long[chanNum].cb_width = p_sri->cb_width_long; p_chpo_long[chanNum].no_of_cb = p_sri->num_cb_long; for( i=0; i<MAX_SHORT_WINDOWS; i++ ) { p_chpo_short[chanNum][i].p_ratio = psy_stvar_short[chanNum].ismr[i]; p_chpo_short[chanNum][i].cb_width = p_sri->cb_width_short; p_chpo_short[chanNum][i].no_of_cb = p_sri->num_cb_short; } } else { /* SCE */ psy_step1(p_time_signal, sample, chanNum); psy_step2(sample, &psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &fft_tbl_long, &fft_tbl_short, chanNum); psy_step3(&psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &psy_var_long[0], &psy_var_short[0]); psy_step4(&psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &psy_var_long[0], &psy_var_short[0]); psy_step5(&part_tbl_long, &part_tbl_short, &psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &psy_var_long[0], &psy_var_short[0]); psy_step6(&part_tbl_long, &part_tbl_short, &psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &psy_var_long[0], &psy_var_short[0]); psy_step7(&part_tbl_long, &part_tbl_short, &psy_var_long[0], &psy_var_short[0]); psy_step8(&part_tbl_long, &part_tbl_short, &psy_var_long[0], &psy_var_short[0]); psy_step9(&part_tbl_long, &part_tbl_short, &psy_var_long[0], &psy_var_short[0]); psy_step10(&part_tbl_long, &part_tbl_short, &psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &psy_var_long[0], &psy_var_short[0]); psy_step11(&part_tbl_long, &part_tbl_short, &psy_stvar_long[chanNum], &psy_stvar_short[chanNum]); psy_step12(&part_tbl_long, &part_tbl_short, &psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &psy_var_long[0], &psy_var_short[0]); psy_step13(&psy_var_long[0], &block_type[chanNum]); psy_step14(p_sri, &part_tbl_long, &part_tbl_short, &psy_stvar_long[chanNum], &psy_stvar_short[chanNum], &psy_var_long[0], &psy_var_short[0]); p_chpo_long[chanNum].p_ratio = psy_stvar_long[chanNum].ismr; p_chpo_long[chanNum].cb_width = p_sri->cb_width_long; p_chpo_long[chanNum].no_of_cb = p_sri->num_cb_long; for( i=0; i<MAX_SHORT_WINDOWS; i++ ) { p_chpo_short[chanNum][i].p_ratio = psy_stvar_short[chanNum].ismr[i]; p_chpo_short[chanNum][i].cb_width = p_sri->cb_width_short; p_chpo_short[chanNum][i].no_of_cb = p_sri->num_cb_short; } } } } } void psy_step1(double* p_time_signal[], double sample[][BLOCK_LEN_LONG*2], int ch) { int i; for(i = 0; i < BLOCK_LEN_LONG; i++){ sample[ch][i] = sample[ch][i+BLOCK_LEN_LONG]; sample[ch][i+BLOCK_LEN_LONG] = p_time_signal[ch][i]; } } void psy_step2(double sample[][BLOCK_LEN_LONG*2], PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, FFT_TABLE_LONG *fft_tbl_long, FFT_TABLE_SHORT *fft_tbl_short, int ch ) { int w,l; double data[2048],a,b; /* FFT for long */ psy_stvar_long->p_fft += BLOCK_LEN_LONG; if(psy_stvar_long->p_fft == BLOCK_LEN_LONG * 3) psy_stvar_long->p_fft = 0; /* windowing */ for(w = 0; w < BLOCK_LEN_LONG; w++){ FFTarray[w].re = fft_tbl_long->hw[(w<<1)] * sample[ch][w<<1]; FFTarray[w].im = fft_tbl_long->hw[(w<<1)+1] * sample[ch][(w<<1)+1]; } realft2048(data); for(w = 0; w < BLOCK_LEN_LONG; w++){ a = data[(w<<1)]; b = data[(w<<1)+1]; psy_stvar_long->fft_r[w+psy_stvar_long->p_fft] = sqrt(a*a + b*b) * sqrt2048; } for(w = 0; w < 16; w++){ a = data[(w<<1)]; b = data[(w<<1)+1]; if( a > 0.0 ){ if( b >= 0.0 ) psy_stvar_long->fft_f[w+psy_stvar_long->p_fft] = atan2( b, a ); else psy_stvar_long->fft_f[w+psy_stvar_long->p_fft] = atan2( b, a )+ M_PI * 2.0; } else if( a < 0.0 ) { psy_stvar_long->fft_f[w+psy_stvar_long->p_fft] = atan2( b, a ) + M_PI; } else { if( b > 0.0 ) psy_stvar_long->fft_f[w+psy_stvar_long->p_fft] = M_PI * 0.5; else if( b < 0.0 ) psy_stvar_long->fft_f[w+psy_stvar_long->p_fft] = M_PI * 1.5; else psy_stvar_long->fft_f[w+psy_stvar_long->p_fft] = 0.0; } } /* FFT for short */ for(l = 0; l < MAX_SHORT_WINDOWS; l++){ /* windowing */ for(w = 0; w < BLOCK_LEN_SHORT; w++){ FFTarray[w].re = fft_tbl_short->hw[w<<1] * sample[ch][OFFSET_FOR_SHORT + (BLOCK_LEN_SHORT * l) + (w<<1)]; FFTarray[w].im = fft_tbl_short->hw[(w<<1)+1] * sample[ch][OFFSET_FOR_SHORT + (BLOCK_LEN_SHORT * l) + (w<<1)+1]; } realft256(data); for(w = 0; w < BLOCK_LEN_SHORT; w++){ a = data[(w<<1)]; b = data[(w<<1)+1]; psy_stvar_short->fft_r[l][w]= sqrt(a*a + b*b) * sqrt256; if( a > 0.0 ){ if( b >= 0.0 ) psy_stvar_short->fft_f[l][w] = atan2( b, a ); else psy_stvar_short->fft_f[l][w] = atan2( b, a )+ M_PI * 2.0; } else if( a < 0.0 ) { psy_stvar_short->fft_f[l][w] = atan2( b, a ) + M_PI; } else { if( b > 0.0 ) psy_stvar_short->fft_f[l][w] = M_PI * 0.5; else if( b < 0.0 ) psy_stvar_short->fft_f[l][w] = M_PI * 1.5; else psy_stvar_short->fft_f[l][w] = 0.0; } } } } void psy_step2MS(PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, int leftChan, int rightChan, int midChan, int sideChan) { int w, l; psy_stvar_long[midChan].p_fft += BLOCK_LEN_LONG; if(psy_stvar_long[midChan].p_fft == BLOCK_LEN_LONG * 3) psy_stvar_long[midChan].p_fft = 0; psy_stvar_long[sideChan].p_fft += BLOCK_LEN_LONG; if(psy_stvar_long[sideChan].p_fft == BLOCK_LEN_LONG * 3) psy_stvar_long[sideChan].p_fft = 0; for (w = 0; w < BLOCK_LEN_LONG; w++) { psy_stvar_long[midChan].fft_r[w+psy_stvar_long[midChan].p_fft] = (psy_stvar_long[leftChan].fft_r[w+psy_stvar_long[leftChan].p_fft]+psy_stvar_long[rightChan].fft_r[w+psy_stvar_long[rightChan].p_fft])*0.5; psy_stvar_long[sideChan].fft_r[w+psy_stvar_long[sideChan].p_fft] = (psy_stvar_long[leftChan].fft_r[w+psy_stvar_long[leftChan].p_fft]-psy_stvar_long[rightChan].fft_r[w+psy_stvar_long[rightChan].p_fft])*0.5; } for (l = 0; l < MAX_SHORT_WINDOWS; l++) { for (w = 0; w < BLOCK_LEN_SHORT; w++) { psy_stvar_short[midChan].fft_r[l][w] = (psy_stvar_short[leftChan].fft_r[l][w]+psy_stvar_short[rightChan].fft_r[l][w])*0.5; psy_stvar_short[sideChan].fft_r[l][w] = (psy_stvar_short[leftChan].fft_r[l][w]-psy_stvar_short[rightChan].fft_r[l][w])*0.5; } } } void psy_step3(PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int w,i; int p1_l,p2_l; p1_l = psy_stvar_long->p_fft - BLOCK_LEN_LONG; if( p1_l < 0 ) p1_l = BLOCK_LEN_LONG * 2; p2_l = p1_l - BLOCK_LEN_LONG; if( p2_l < 0 ) p2_l = BLOCK_LEN_LONG; for(w = 0; w < 16; w++){ psy_var_long->r_pred[w] = 2.0 * psy_stvar_long->fft_r[p1_l + w] - psy_stvar_long->fft_r[p2_l + w]; psy_var_long->f_pred[w] = 2.0 * psy_stvar_long->fft_f[p1_l + w] - psy_stvar_long->fft_f[p2_l + w]; } for(w = 0; w < BLOCK_LEN_SHORT; w++){ psy_var_short->r_pred[0][w] = 2.0 * psy_stvar_short->last7_fft_r[w] - psy_stvar_short->last6_fft_r[w]; psy_var_short->f_pred[0][w] = 2.0 * psy_stvar_short->last7_fft_f[w] - psy_stvar_short->last6_fft_f[w]; psy_var_short->r_pred[1][w] = 2.0 * psy_stvar_short->fft_r[0][w] - psy_stvar_short->last7_fft_r[w]; psy_var_short->f_pred[1][w] = 2.0 * psy_stvar_short->fft_f[0][w] - psy_stvar_short->last7_fft_f[w]; } for(i = 2; i < MAX_SHORT_WINDOWS; i++){ for(w = 0; w < BLOCK_LEN_SHORT; w++){ psy_var_short->r_pred[i][w] = 2.0 * psy_stvar_short->fft_r[i - 1][w] - psy_stvar_short->fft_r[i - 2][w]; psy_var_short->f_pred[i][w] = 2.0 * psy_stvar_short->fft_f[i - 1][w] - psy_stvar_short->fft_f[i - 2][w]; } } for(w = 0; w < BLOCK_LEN_SHORT; w++){ psy_stvar_short->last6_fft_r[w] = psy_stvar_short->fft_r[6][w]; psy_stvar_short->last6_fft_f[w] = psy_stvar_short->fft_f[6][w]; psy_stvar_short->last7_fft_r[w] = psy_stvar_short->fft_r[7][w]; psy_stvar_short->last7_fft_f[w] = psy_stvar_short->fft_f[7][w]; } } void psy_step4(PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int w,i; double r,f,rp,fp; for(i = 0; i < MAX_SHORT_WINDOWS; i++){ for(w = 0; w < BLOCK_LEN_SHORT; w++){ r = psy_stvar_short->fft_r[i][w]; f = psy_stvar_short->fft_f[i][w]; rp = psy_var_short->r_pred[i][w]; fp = psy_var_short->f_pred[i][w]; if( fabs(r) + fabs(rp) != 0.0 ) /* Replacing with something faster psy_var_short->c[i][w] = sqrt( psy_sqr(r*cos(f) - rp*cos(fp)) +psy_sqr(r*sin(f) - rp*sin(fp)) )/ ( r + fabs(rp) ) ; */ psy_var_short->c[i][w] = sqrt( r*r+rp*rp-2*r*rp*cos(f+fp) )/ ( r + fabs(rp) ); else psy_var_short->c[i][w] = 0.0; /* tmp */ } } for(w = 0; w < 16; w++){ r = psy_stvar_long->fft_r[psy_stvar_long->p_fft+w]; f = psy_stvar_long->fft_f[psy_stvar_long->p_fft+w]; rp = psy_var_long->r_pred[w]; fp = psy_var_long->f_pred[w]; if( fabs(r) + fabs(rp) != 0.0 ) /* Replacing with something faster psy_var_long->c[w] = sqrt( psy_sqr(r*cos(f) - rp*cos(fp)) +psy_sqr(r*sin(f) - rp*sin(fp)) )/ ( r + fabs(rp) ); */ psy_var_long->c[w] = sqrt( r*r+rp*rp-2*r*rp*cos(f+fp) )/ ( r + fabs(rp) ); else psy_var_long->c[w] = 0.0; /* tmp */ } for(w = 16; w < 416; w+=8) { double temp_c = 0.0; for(i = 0; i < MAX_SHORT_WINDOWS; i++) { temp_c += psy_var_short->c[i][w/8]; } temp_c = temp_c/8.0; for(i = 0; i < MAX_SHORT_WINDOWS; i++) { psy_var_long->c[w+i] = temp_c; } } for(w = 416; w < BLOCK_LEN_LONG; w++){ psy_var_long->c[w] = 0.4; } } void psy_step4MS(PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short, int leftChan, int rightChan, int midChan, int sideChan) { int b, i; for (b = 0; b < NPART_LONG; b++) psy_var_long[midChan].c[b] = psy_var_long[sideChan].c[b] = min(psy_var_long[leftChan].c[b], psy_var_long[rightChan].c[b]); for (i = 0; i < MAX_SHORT_WINDOWS; i++) for (b = 0; b < NPART_SHORT; b++) psy_var_short[midChan].c[i][b] = psy_var_short[sideChan].c[i][b] = min(psy_var_short[leftChan].c[i][b], psy_var_short[rightChan].c[i][b]); } void psy_step5(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int b,w,i; double tmp_cb; for(b = 0; b < part_tbl_long->len; b++){ psy_var_long->e[b] = 0.0; tmp_cb = 0.0; for(w = part_tbl_long->w_low[b]; w < part_tbl_long->w_high[b]; w++){ psy_var_long->e[b] += psy_sqr(psy_stvar_long->fft_r[psy_stvar_long->p_fft+w]); tmp_cb += psy_sqr(psy_stvar_long->fft_r[psy_stvar_long->p_fft+w]) * psy_var_long->c[w]; } psy_var_long->cb[b] = tmp_cb; } for(i = 0; i < MAX_SHORT_WINDOWS; i++){ for(b = 0; b < part_tbl_short->len; b++){ psy_var_short->e[i][b] = 0.0; tmp_cb = 0.0; for(w = part_tbl_short->w_low[b]; w < part_tbl_short->w_high[b]; w++){ psy_var_short->e[i][b] += psy_sqr(psy_stvar_short->fft_r[i][w]); tmp_cb += psy_sqr(psy_stvar_short->fft_r[i][w]) * psy_var_short->c[i][w]; } psy_var_short->cb[i][b] = tmp_cb; } } } void psy_step6(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int b,bb,i; double ecb,ct; double sprd; for(b = 0; b < part_tbl_long->len; b++){ ecb = 0.0; ct = 0.0; for(bb = 0; bb < part_tbl_long->len; bb++){ sprd = part_tbl_long->dyn->spreading[bb][b]; ecb += psy_var_long->e[bb] * sprd; ct += psy_var_long->cb[bb] * sprd; } if (ecb!=0.0) { psy_var_long->cbb[b] = ct / ecb; psy_stvar_long->en[b] = psy_var_long->en[b] = ecb * part_tbl_long->dyn->rnorm[b]; } else { psy_var_long->cbb[b] = 0.0; psy_stvar_long->en[b] = psy_var_long->en[b] = 0; } } for(i = 0; i < MAX_SHORT_WINDOWS; i++){ for(b = 0; b < part_tbl_short->len; b++){ ecb = 0.0; ct = 0.0; for(bb = 0; bb < part_tbl_short->len; bb++){ sprd = part_tbl_short->dyn->spreading[bb][b]; ecb += psy_var_short->e[i][bb] * sprd; ct += psy_var_short->cb[i][bb] * sprd; } if (ecb!=0.0) { psy_var_short->cbb[i][b] = ct / ecb; psy_stvar_short->en[i][b] = psy_var_short->en[i][b] = ecb * part_tbl_short->dyn->rnorm[b]; } else { psy_var_short->cbb[i][b] = 0.0; psy_stvar_short->en[i][b] = psy_var_short->en[i][b] = 0; } } } } void psy_step7(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short) { int b,i; for(b = 0; b < part_tbl_long->len; b++){ if (psy_var_long->cbb[b] > 0.0) { psy_var_long->tb[b] = -0.299 - 0.43 * log(psy_var_long->cbb[b]); } else { psy_var_long->tb[b] = 1.0; } if( psy_var_long->tb[b] > 1.0 ) psy_var_long->tb[b] = 1.0; else if( psy_var_long->tb[b] < 0.0 ) psy_var_long->tb[b] = 0.0; // if ((psy_var_long->tb[b]<1.0)&&(psy_var_long->tb[b]>0.5)) // printf("%d\t%.2f\n", b, psy_var_long->tb[b]); } for(i = 0; i < MAX_SHORT_WINDOWS; i++){ for(b = 0; b < part_tbl_short->len; b++){ if (psy_var_short->cbb[i][b]>0.0) { psy_var_short->tb[i][b] = -0.299 - 0.43 * log(psy_var_short->cbb[i][b]); } else { psy_var_short->tb[i][b] = 1.0; } if( psy_var_short->tb[i][b] > 1.0 ) psy_var_short->tb[i][b] = 1.0; else if( psy_var_short->tb[i][b] < 0.0 ) psy_var_short->tb[i][b] = 0.0; // if ((psy_var_short->tb[i][b]<1.0)&&(psy_var_short->tb[i][b]>0.5)) // printf("%d\t%.2f\n", b, psy_var_short->tb[i][b]); } } } void psy_step7MS(PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short, int leftChan, int rightChan, int midChan, int sideChan) { int b, i; for (b = 0; b < NPART_LONG; b++) { psy_var_long[midChan].tb[b] = psy_var_long[leftChan].tb[b]; psy_var_long[sideChan].tb[b] = psy_var_long[rightChan].tb[b]; } for (i = 0; i < MAX_SHORT_WINDOWS; i++) for (b = 0; b < NPART_SHORT; b++) { psy_var_short[midChan].tb[i][b] = psy_var_short[leftChan].tb[i][b]; psy_var_short[sideChan].tb[i][b] = psy_var_short[rightChan].tb[i][b]; } } void psy_step8(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short) { int b,i; double tmn = 18.0, nmt = 6.0; for(b = 0; b < part_tbl_long->len; b++) { psy_var_long->snr[b] = psy_var_long->tb[b] * tmn + (1.0 - psy_var_long->tb[b] ) * nmt; } for(i = 0; i < MAX_SHORT_WINDOWS; i++){ for(b = 0; b < part_tbl_short->len; b++) psy_var_short->snr[i][b] = psy_var_short->tb[i][b] * tmn + (1.0 - psy_var_short->tb[i][b] ) * nmt ; } } void psy_step9(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int b,i; for(b = 0; b < part_tbl_long->len; b++) psy_var_long->bc[b] = pow(10.0, -psy_var_long->snr[b]/10.0); for(i = 0; i < MAX_SHORT_WINDOWS; i++){ for(b = 0; b < part_tbl_short->len; b++) psy_var_short->bc[i][b] = pow(10.0, -psy_var_short->snr[i][b]/10.0); } } void psy_step10(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int b,i; psy_stvar_long->p_nb += NPART_LONG; if( psy_stvar_long->p_nb == NPART_LONG*2 ) psy_stvar_long->p_nb = 0; for(b = 0; b < part_tbl_long->len; b++){ psy_stvar_long->nb[psy_stvar_long->p_nb + b] = psy_var_long->en[b] * psy_var_long->bc[b]; } for(i = 0; i < MAX_SHORT_WINDOWS; i++){ for(b = 0; b < part_tbl_short->len; b++){ psy_stvar_short->nb[i][b] = psy_var_short->en[i][b] * psy_var_short->bc[i][b]; } } } void psy_step11(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short ) { int b,i; int p1,p2; double temp; p1 = psy_stvar_long->p_nb; if( p1 == 0 ) p2 = NPART_LONG; else if( p1 == NPART_LONG ) p2 = 0; for(b = 0; b < part_tbl_long->len; b++) { temp = min( psy_stvar_long->nb[p1+b], 2.0*psy_stvar_long->nb[p2+b]); if (temp > 0.01) psy_stvar_long->nb[p1+b] = temp; } for(b = 0; b < part_tbl_short->len; b++){ temp = min( psy_stvar_short->nb[0][b], 1.0*psy_stvar_short->last7_nb[b]); if (temp > 0.01) psy_stvar_short->nb[0][b] = temp; } for(b = 0; b < part_tbl_short->len; b++){ psy_stvar_short->last7_nb[b] = psy_stvar_short->nb[7][b]; } for(i = 1; i < MAX_SHORT_WINDOWS; i++){ for(b = 0; b < part_tbl_short->len; b++){ temp = min( psy_stvar_short->nb[i][b], 1.0*psy_stvar_short->nb[i - 1][b]); if (temp > 0.01) psy_stvar_short->nb[i][b] = temp; } } } void psy_step11MS(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, int leftChan, int rightChan, int midChan, int sideChan) { #if 1 // LAME's version int b, i, p1; double tempM, tempS; p1 = psy_stvar_long[leftChan].p_nb; for(b = 0; b < part_tbl_long->len; b++) { tempM = max(psy_stvar_long[midChan].nb[p1+b], min(part_tbl_long->dyn->bmax[b]*psy_stvar_long[sideChan].en[b], psy_stvar_long[sideChan].nb[p1+b])); tempS = max(psy_stvar_long[sideChan].nb[p1+b], min(part_tbl_long->dyn->bmax[b]*psy_stvar_long[midChan].en[b], psy_stvar_long[midChan].nb[p1+b])); if ((psy_stvar_long[leftChan].nb[p1+b] <= 1.58*psy_stvar_long[rightChan].nb[p1+b])&&(psy_stvar_long[rightChan].nb[p1+b] <= 1.58*psy_stvar_long[leftChan].nb[p1+b])) { psy_stvar_long[midChan].nb[p1+b] = tempM; psy_stvar_long[sideChan].nb[p1+b] = tempS; } } for (i = 0; i < MAX_SHORT_WINDOWS; i++) { for(b = 0; b < part_tbl_short->len; b++) { tempM = max(psy_stvar_short[midChan].nb[i][b], min(part_tbl_short->dyn->bmax[b]*psy_stvar_short[sideChan].en[i][b], psy_stvar_short[sideChan].nb[i][b])); tempS = max(psy_stvar_short[sideChan].nb[i][b], min(part_tbl_short->dyn->bmax[b]*psy_stvar_short[midChan].en[i][b], psy_stvar_short[midChan].nb[i][b])); if ((psy_stvar_short[leftChan].nb[i][b] <= 1.58*psy_stvar_short[rightChan].nb[i][b])&&(psy_stvar_short[rightChan].nb[i][b] <= 1.58*psy_stvar_short[leftChan].nb[i][b])) { psy_stvar_short[midChan].nb[i][b] = tempM; psy_stvar_short[sideChan].nb[i][b] = tempS; } } } #else int b, i,p1; double t; double tempL, tempR, tempM, tempS; p1 = psy_stvar_long[leftChan].p_nb; for(b = 0; b < part_tbl_long->len; b++) { if (psy_stvar_long[sideChan].nb[p1+b] != 0.0) t = psy_stvar_long[midChan].nb[p1+b]/psy_stvar_long[sideChan].nb[p1+b]; else t = 0; if (t>1) t = 1/t; tempL = max(psy_stvar_long[leftChan].nb[p1+b]*t, min(psy_stvar_long[leftChan].nb[p1+b], part_tbl_long->dyn->bmax[b]*psy_stvar_long[leftChan].en[b])); tempR = max(psy_stvar_long[rightChan].nb[p1+b]*t, min(psy_stvar_long[rightChan].nb[p1+b], part_tbl_long->dyn->bmax[b]*psy_stvar_long[rightChan].en[b])); t = min(tempL,tempR); tempM = min(t, max(psy_stvar_long[midChan].nb[p1+b], min(part_tbl_long->dyn->bmax[b]*psy_stvar_long[sideChan].en[b], psy_stvar_long[sideChan].nb[p1+b]))); tempS = min(t, max(psy_stvar_long[sideChan].nb[p1+b], min(part_tbl_long->dyn->bmax[b]*psy_stvar_long[midChan].en[b], psy_stvar_long[midChan].nb[p1+b]))); if ((psy_stvar_long[leftChan].nb[p1+b] >= 1.58*psy_stvar_long[rightChan].nb[p1+b])&&(psy_stvar_long[rightChan].nb[p1+b] >= 1.58*psy_stvar_long[leftChan].nb[p1+b])) { psy_stvar_long[midChan].nb[p1+b] = tempM; psy_stvar_long[sideChan].nb[p1+b] = tempS; psy_stvar_long[leftChan].nb[p1+b] = tempL; psy_stvar_long[rightChan].nb[p1+b] = tempR; } } for (i = 0; i < MAX_SHORT_WINDOWS; i++) { for(b = 0; b < part_tbl_short->len; b++) { if (psy_stvar_short[sideChan].nb[i][b] != 0.0) t = psy_stvar_short[midChan].nb[i][b]/psy_stvar_short[sideChan].nb[i][b]; else t = 0; if (t>1) t = 1/t; tempL = max(psy_stvar_short[leftChan].nb[i][b]*t, min(psy_stvar_short[leftChan].nb[i][b], part_tbl_short->dyn->bmax[b]*psy_stvar_short[leftChan].en[i][b])); tempR = max(psy_stvar_short[rightChan].nb[i][b]*t, min(psy_stvar_short[rightChan].nb[i][b], part_tbl_short->dyn->bmax[b]*psy_stvar_short[rightChan].en[i][b])); t = min(tempL,tempR); tempM = min(t, max(psy_stvar_short[midChan].nb[i][b], min(part_tbl_short->dyn->bmax[b]*psy_stvar_short[sideChan].en[i][b], psy_stvar_short[sideChan].nb[i][b]))); tempS = min(t, max(psy_stvar_short[sideChan].nb[i][b], min(part_tbl_short->dyn->bmax[b]*psy_stvar_short[midChan].en[i][b], psy_stvar_short[midChan].nb[i][b]))); if ((psy_stvar_short[leftChan].nb[i][b] >= 1.58*psy_stvar_short[rightChan].nb[i][b])&&(psy_stvar_short[rightChan].nb[i][b] >= 1.58*psy_stvar_short[leftChan].nb[i][b])) { psy_stvar_short[midChan].nb[i][b] = tempM; psy_stvar_short[sideChan].nb[i][b] = tempS; psy_stvar_short[leftChan].nb[i][b] = tempL; psy_stvar_short[rightChan].nb[i][b] = tempR; } } } #endif } void psy_step12(PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int b,i,shb; double temp; double tot, mx, estot[8]; psy_var_long->pe = 0.0; for(b = 0; b < part_tbl_long->len; b++){ temp = part_tbl_long->width[b] * log((psy_stvar_long->nb[psy_stvar_long->p_nb + b] + 0.0000000001) / (psy_var_long->e[b] + 0.0000000001)); temp = min(0,temp); psy_var_long->pe -= temp; } for (i=0; i < MAX_SHORT_WINDOWS; i++) { estot[i]=0; for ( b = 0; b < NPART_SHORT; b++) estot[i] += psy_var_short->e[i][b]; if (estot[i] != 0.0) estot[i] /= NPART_SHORT; } tot = mx = estot[0]; for (i=1; i < MAX_SHORT_WINDOWS; i++) { tot += estot[i]; mx = max(mx, estot[i]); } shb = 0; if (psy_var_long->pe > 5600) shb = 1; if ((mx/tot) > 0.3) shb = 1; if (shb) psy_var_long->pe = 1; else psy_var_long->pe = 0; } void psy_step13(PSY_VARIABLE_LONG *psy_var_long, enum WINDOW_TYPE *block_type ) { if(psy_var_long->pe == 1) { *block_type = ONLY_SHORT_WINDOW; } else { *block_type = ONLY_LONG_WINDOW; } } void psy_step14(SR_INFO *p_sri, PARTITION_TABLE_LONG *part_tbl_long, PARTITION_TABLE_SHORT *part_tbl_short, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short ) { int b, n, w, i; int w_low, w_high; double thr, minthr; w_high = 0; for(n = 0; n < p_sri->num_cb_long; n++){ w_low = w_high; w_high += p_sri->cb_width_long[n]; psy_var_long->epart[n] = 0.0; for(w = w_low; w < w_high; w++){ psy_var_long->epart[n] += psy_sqr(psy_stvar_long->fft_r[psy_stvar_long->p_fft + w]); } } for(b = 0; b < part_tbl_long->len; b++){ thr = psy_stvar_long->nb[psy_stvar_long->p_nb + b] / part_tbl_long->width[b]; for(w = part_tbl_long->w_low[b]; w < part_tbl_long->w_high[b]; w++){ psy_var_long->thr[w] = thr; } } w_high = 0; for(n = 0; n < p_sri->num_cb_long; n++){ w_low = w_high; w_high += p_sri->cb_width_long[n]; minthr = psy_var_long->thr[w_low]; for(w = w_low+1; w < w_high; w++){ if(psy_var_long->thr[w] < minthr){ minthr = psy_var_long->thr[w]; } } psy_var_long->npart[n] = minthr * (w_high - w_low); } for(n = 0; n < p_sri->num_cb_long; n++){ if (psy_var_long->epart[n]!=0.0) { psy_stvar_long->ismr[n] = psy_var_long->npart[n] / psy_var_long->epart[n]; } else { psy_stvar_long->ismr[n] = 0.0; } } for(i = 0; i < MAX_SHORT_WINDOWS; i++){ w_high = 0; for(n = 0; n < p_sri->num_cb_short; n++){ w_low = w_high; w_high += p_sri->cb_width_short[n]; psy_var_short->epart[i][n] = 0.0; for(w = w_low; w < w_high; w++){ psy_var_short->epart[i][n] += psy_sqr(psy_stvar_short->fft_r[i][w]); } } for(b = 0; b < part_tbl_short->len; b++){ thr = psy_stvar_short->nb[i][b] / part_tbl_short->width[b]; for(w = part_tbl_short->w_low[b]; w < part_tbl_short->w_high[b]; w++){ psy_var_short->thr[i][w] = thr; } } w_high = 0; for(n = 0; n < p_sri->num_cb_short; n++){ w_low = w_high; w_high += p_sri->cb_width_short[n]; minthr = psy_var_short->thr[i][w_low]; for(w = w_low + 1; w < w_high; w++){ if(psy_var_short->thr[i][w] < minthr){ minthr = psy_var_short->thr[i][w]; } } psy_var_short->npart[i][n] = minthr * (w_high - w_low); } for(n = 0; n < p_sri->num_cb_short; n++){ if (psy_var_short->epart[i][n]!=0.0) { psy_stvar_short->ismr[i][n] = psy_var_short->npart[i][n] / psy_var_short->epart[i][n]; } else { psy_stvar_short->ismr[i][n] = 0.0; } } } } void psy_step15(SR_INFO *p_sri, PSY_STATVARIABLE_LONG *psy_stvar_long, PSY_STATVARIABLE_SHORT *psy_stvar_short, PSY_VARIABLE_LONG *psy_var_long, PSY_VARIABLE_SHORT *psy_var_short, int leftChan, int rightChan, int midChan, int sideChan ) { int b, i; double temp, x1, x2, db; for (b = 0; b < p_sri->num_cb_long; b++) { x1 = min(psy_var_long[0].npart[b],psy_var_long[1].npart[b]); x2 = max(psy_var_long[0].npart[b],psy_var_long[1].npart[b]); if (x2 >= 1000*x1) db=30; else db = 10*log10(x2/x1); temp = 0.35*(db)/5.0; // printf("%d\t%f\n", b, temp); if (temp < 0.35) { psy_stvar_long[rightChan].use_ms[b] = 1; psy_stvar_long[leftChan].ismr[b] = psy_stvar_long[midChan].ismr[b]; psy_stvar_long[rightChan].ismr[b] = psy_stvar_long[sideChan].ismr[b]; } else { psy_stvar_long[rightChan].use_ms[b] = 0; } } for (i = 0; i < 8; i++) { for (b = 0; b < p_sri->num_cb_short; b++) { x1 = min(psy_var_short[0].npart[i][b],psy_var_short[1].npart[i][b]); x2 = max(psy_var_short[0].npart[i][b],psy_var_short[1].npart[i][b]); if (x2 >= 1000*x1) db=30; else db = 10*log10(x2/x1); temp = 0.35*(db)/5.0; // printf("%d\t%f\n", b, temp); if (temp < 0.35) { psy_stvar_short[rightChan].use_ms[i][b] = 1; psy_stvar_short[leftChan].ismr[i][b] = psy_stvar_short[midChan].ismr[i][b]; psy_stvar_short[rightChan].ismr[i][b] = psy_stvar_short[sideChan].ismr[i][b]; } else { psy_stvar_short[rightChan].use_ms[i][b] = 0; } } } }