diff --git a/apps/renderer.c b/apps/renderer.c index 10e5f249c9ce4c6032b7d792912acaca74f59eb4..61c98952488d83c8c7202e4c651d76a06ef1f209 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1194,7 +1194,7 @@ int main( /* Convert from int to float and from interleaved to packed */ convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer ); #ifdef IVAS_FLOAT_FIXED - *outBuffer.pq_fact = 16 - ( gd_bits + 1 ); + *outBuffer.pq_fact = 16 - ( gd_bits); convertInputBuffer_fx( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inInt32Buffer, *outBuffer.pq_fact ); #endif int16_t num_subframes, sf_idx; diff --git a/lib_com/cnst.h b/lib_com/cnst.h index 6296e2fc1bb8d9666f8bf071a657aabcf03ac698..e2073f223526cfc2836da1f0ea438a125e0ef555 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -1966,6 +1966,7 @@ typedef enum _DCTTYPE #define INV_PREECHO_SMOOTH_LENP1 ( 1 / ( PREECHO_SMOOTH_LEN + 1.0 ) ); #define EPSILON 0.000000000000001f +#define EPSILON_fx 0 #define MAX_SEGMENT_LENGTH 480 #define NUM_TIME_SWITCHING_BLOCKS 4 diff --git a/lib_rend/ivas_limiter.c b/lib_rend/ivas_limiter.c index 3cc50fffaf6135c9f8d8676faebd11253101d8c6..e57a0cc58019cf7c9dd784c26c15471534693ab5 100644 --- a/lib_rend/ivas_limiter.c +++ b/lib_rend/ivas_limiter.c @@ -43,7 +43,51 @@ #define ATTACK_CNST_16k ( 2027355264 ) // Q31 #define ATTACK_CNST_8k ( 1913946752 ) // Q31 #endif - +Word32 release_cnst_table[201] = //Q31 +{ + 2106670080, + 2107727232, 2108757120, 2109760640, 2110738432, 2111691008, + 2112619136, 2113523328, 2114404352, 2115262592, 2116098816, + 2116913408, 2117707136, 2118480256, 2119233536, 2119967360, + 2120682240, 2121378688, 2122057088, 2122717952, 2123361792, + 2123988992, 2124599936, 2125195136, 2125774848, 2126339584, + 2126889728, 2127425536, 2127947520, 2128456064, 2128951296, + 2129433856, 2129903744, 2130361600, 2130807424, 2131241728, + 2131664768, 2132076928, 2132478208, 2132869248, 2133250048, + 2133620992, 2133982208, 2134334080, 2134676864, 2135010688, + 2135335936, 2135652608, 2135961088, 2136261504, 2136554112, + 2136839168, 2137116800, 2137387136, 2137650560, 2137907072, + 2138156928, 2138400256, 2138637184, 2138867968, 2139092864, + 2139311744, 2139524992, 2139732736, 2139934976, 2140131968, + 2140323840, 2140510720, 2140692736, 2140870016, 2141042688, + 2141210752, 2141374592, 2141534080, 2141689344, 2141840640, + 2141987968, 2142131456, 2142271232, 2142407424, 2142539904, + 2142669056, 2142794752, 2142917248, 2143036544, 2143152640, + 2143265792, 2143375872, 2143483264, 2143587712, 2143689472, + 2143788544, 2143885056, 2143979136, 2144070656, 2144159872, + 2144246656, 2144331264, 2144413568, 2144493824, 2144571904, + 2144647936, 2144722048, 2144794240, 2144864512, 2144932864, + 2144999552, 2145064448, 2145127680, 2145189248, 2145249152, + 2145307520, 2145364480, 2145419776, 2145473792, 2145526272, + 2145577472, 2145627264, 2145675776, 2145723008, 2145768960, + 2145813760, 2145857408, 2145899904, 2145941376, 2145981696, + 2146020864, 2146059136, 2146096384, 2146132608, 2146167936, + 2146202368, 2146235776, 2146268416, 2146300160, 2146331136, + 2146361216, 2146390528, 2146419200, 2146446976, 2146474112, + 2146500480, 2146526208, 2146551168, 2146575488, 2146599296, + 2146622464, 2146644864, 2146666880, 2146688128, 2146708992, + 2146729216, 2146748928, 2146768128, 2146786816, 2146805120, + 2146822784, 2146840064, 2146856960, 2146873344, 2146889216, + 2146904832, 2146919936, 2146934656, 2146948992, 2146962944, + 2146976640, 2146989824, 2147002752, 2147015296, 2147027584, + 2147039488, 2147051136, 2147062400, 2147073408, 2147084160, + 2147094528, 2147104768, 2147114624, 2147124352, 2147133696, + 2147142912, 2147151744, 2147160448, 2147168896, 2147177088, + 2147185152, 2147192960, 2147200512, 2147207936, 2147215104, + 2147222144, 2147229056, 2147235712, 2147242112, 2147248384, + 2147254656, 2147260544, 2147266432, 2147272064, 2147277568, + +}; /*-------------------------------------------------------------------* * detect_strong_saturations() * @@ -111,7 +155,7 @@ static Word16 detect_strong_saturations_fx( const Word16 BER_detect, /* i : BER detect flag */ Word16 *strong_saturation_cnt, /* i/o: counter of strong saturations */ const Word32 max_val, /* i : maximum absolute value */ - Word16 *frame_gain, /* i/o: frame gain value */ + Word32 *frame_gain, /* i/o: frame gain value */ Word16 q_factor /*Q factor of the output samples*/ ) { @@ -144,10 +188,10 @@ static Word16 detect_strong_saturations_fx( if ( apply_strong_limiting ) { - IF( LT_16 (* frame_gain , 4915) ) // Q14 of 0.3 is compared + IF( LT_32( *frame_gain, 322122547 ) ) // Q30 of 0.3 is compared { //*frame_gain /= 3.0f; - *frame_gain = lshr(divide1616( *frame_gain, 24576 ) , 2);//Q14 + *frame_gain = L_shl( divide3216( *frame_gain, 24576 ), 14 ); // Q30 } ELSE { @@ -196,7 +240,7 @@ ivas_error ivas_limiter_open( } hLimiter->sampling_rate = sampling_rate; hLimiter->gain = 1.f; - hLimiter->gain_fx = ONE_IN_Q14; + hLimiter->gain_fx = ONE_IN_Q30; hLimiter->release_heuristic = 0.f; hLimiter->release_heuristic_fx = 0; hLimiter->attack_constant = powf( 0.01f, 1.0f / ( IVAS_LIMITER_ATTACK_SECONDS * sampling_rate ) ); @@ -217,6 +261,7 @@ ivas_error ivas_limiter_open( } + hLimiter->attack_constant_fx = attack_cnst_fx; hLimiter->strong_saturation_count = 0; @@ -387,14 +432,12 @@ void limiter_process_fx( Word16 i, c; Word32 tmp, max_val; Word32 *sample; - Word32 attack_constant; - Word32 releaseHeuristic; + Word32 releaseHeuristic, releaseHeuristic_cnst, releaseHeuristic_cnst_2; Word16 apply_limiting, apply_strong_limiting; Word32 **output; - Word16 num_channels, q_fact_gain, div32, compare_value; - Word32 sampling_rate, release_constant; - Word16 gain, frame_gain, fact, fact_2, exp_pow, exp_pow_2 = 0, result; - Word32 mul; + Word16 num_channels, q_fact_gain, scale, result; + Word32 sampling_rate, release_constant, compare_value; + Word32 div32, gain, frame_gain, attack_constant; /* return early if given nonsensical values */ IF ( hLimiter == NULL || output_frame <= 0 ) @@ -410,7 +453,6 @@ void limiter_process_fx( num_channels = hLimiter->num_channels; sampling_rate = hLimiter->sampling_rate; attack_constant = hLimiter->attack_constant_fx; - /*-----------------------------------------------------------------* * Find highest absolute peak sample value *-----------------------------------------------------------------*/ @@ -442,40 +484,36 @@ void limiter_process_fx( * keep the gain curve smoother if the threshold is exceeded in many frames * in a short span of time. */ - Word16 sample_num = 0; - SWITCH (sampling_rate) - { - case 48000: - sample_num = L_SUBFRAME_48k; - BREAK; - case 32000: - sample_num = L_SUBFRAME_32k; - BREAK; - case 16000: - sample_num = L_SUBFRAME_16k; - BREAK; - case 8000: - sample_num = L_SUBFRAME_8k; - BREAK; - - + SWITCH( output_frame ) + { + case 960: + case 640: + case 320: + case 160: + releaseHeuristic_cnst = 85899345; + releaseHeuristic_cnst_2 = 21474836; + break; + default: + releaseHeuristic_cnst = 21474836; + releaseHeuristic_cnst_2 = 5368709; + break; } releaseHeuristic = hLimiter->release_heuristic_fx; - q_fact_gain = Q14; - if ( max_val > threshold ) + q_fact_gain = Q30; + IF (GT_32( max_val , threshold) ) { - frame_gain = shr(divide3232( threshold, max_val ),1);//to q14 - releaseHeuristic = min( ONE_IN_Q30, L_add( releaseHeuristic, 21474836 ) ); - // release_constant = powf( 0.01f, 1.0f / ( 0.005f * powf( 200.f, .02 ) * sampling_rate ) ); + frame_gain = L_shl(divide3232( threshold, max_val ),15);//to q30 + releaseHeuristic = min( ONE_IN_Q30, L_add( releaseHeuristic, releaseHeuristic_cnst ) );// releaseHeuristic_cnst is Q30 of ( 4.f * output_frame / sampling_rate ) + // release_constant = powf( 0.01f, 1.0f / ( 0.005f * powf( 200.f, .08 ) * sampling_rate ) ); /* Unoptimized code for reference */ /* releaseHeuristic = min( 1.f, releaseHeuristic + ( (float) 2.f * output_frame / sampling_rate / adaptiveReleaseWindowLengthInSeconds ) ); * ^ * React faster when release time should be increased */ } - else + ELSE { - releaseHeuristic = max( 0, L_sub( releaseHeuristic, 5368709 ) ); + releaseHeuristic = max( 0, L_sub( releaseHeuristic, releaseHeuristic_cnst_2 ) );//releaseHeuristic_cnst_2 is Q30 of output_frame / sampling_rate ) /* Unoptimized code for reference */ /*releaseHeuristic = max( 0.f, releaseHeuristic - ( (float) 0.5f * output_frame / sampling_rate / adaptiveReleaseWindowLengthInSeconds ) ); * ^ @@ -483,25 +521,24 @@ void limiter_process_fx( */ /* No samples above threshold and gain from previous frame is already 1.f, * therefore gain == 1.f for the entire frame. Skip processing. */ - if ( gain >= ( lshl( 1, q_fact_gain ) )) + IF ( GE_32(gain , ( L_shl( 1, q_fact_gain ) ))) { apply_limiting = 0; } /* No samples above threshold but gain from previous frame is not 1.f, * transition to gain == 1.f */ - frame_gain = lshl( 1, q_fact_gain ); + frame_gain = L_shl( 1, q_fact_gain ); } - /* Detection of very strong saturations */ if ( strong_saturation_cnt != NULL ) { apply_strong_limiting = detect_strong_saturations_fx( BER_detect, strong_saturation_cnt, max_val, &frame_gain, q_factor ); } - compare_value = 3277;//Q14 of 0.1f + compare_value = 107374182; // Q30 of 0.1f /* Limit gain reduction to 20dB. Any peaks that require gain reduction * higher than this are most likely due to bit errors during decoding */ - if ( frame_gain < compare_value && !apply_strong_limiting ) + IF ( LT_32(frame_gain , compare_value) && !apply_strong_limiting ) { frame_gain = compare_value; } @@ -513,14 +550,10 @@ void limiter_process_fx( * The denominator of the second argument determines after how many * samples the gain curve will reach 99% of its target value */ - mul = Mpy_32_32( 1025941011, releaseHeuristic ) >> 10; // Q16 - /*For powf(200.0f,x)*/ - fact = L_Extract_lc( mul, &exp_pow ); - result = extract_l( Pow2( 14, fact ) ); - div32 = divide3232( L_shl( 1, ( 14 - exp_pow + 1 ) ), L_mult( result, sample_num ) ); - /*For powf(0.01f,x)*/ - fact_2 = shr(norm_l(div32 ),1) ; - release_constant = pow_10( L_shl( -div32, fact_2 ), &exp_pow_2 ); + div32 = 5368709; // Q30 of 0.005 which is the lowest values for (output_frame / sampling_rate) + + result = BASOP_Util_Divide3232_Scale( releaseHeuristic, div32, &scale ); + release_constant = release_cnst_table[shr( result, ( 15 - scale ) )]; /* Unoptimized code for reference */ /* releaseTimeInSeconds = 0.005f * powf(200.f, releaseHeuristic); <-- Map heuristic value (0; 1) exponentially to range (0.005; 1) * release_constant = powf( 0.01f, 1.0f / ( releaseTimeInSeconds * sampling_rate ) ); @@ -529,26 +562,25 @@ void limiter_process_fx( /*-----------------------------------------------------------------* * Apply limiting *-----------------------------------------------------------------*/ - - for ( i = 0; i < output_frame; i++ ) + + FOR ( i = 0; i < output_frame; i++ ) { /* Update gain */ - if ( frame_gain < gain ) + IF( LT_32(frame_gain , gain) ) { - gain = add(extract_h(Mpy_32_16_r(attack_constant ,( sub(gain , frame_gain) ))) , frame_gain);//q14 + gain = L_add( Mpy_32_32( attack_constant, ( L_sub( gain, frame_gain ) ) ), frame_gain ); // q30 } - else + ELSE { - Word16 temp = extract_l( L_lshl( Mpy_32_16_r( release_constant, sub( gain, frame_gain ) ), ( 15 - (exp_pow_2) ) ) ); - gain = add( temp, frame_gain ); // q14 + gain = L_add( Mpy_32_32( release_constant, ( L_sub( gain, frame_gain ) ) ), frame_gain ); // q30 } - for ( c = 0; c < num_channels; c++ ) + FOR ( c = 0; c < num_channels; c++ ) { sample = &output[c][i]; /* Apply gain */ - *sample = Mpy_32_16_r(L_lshl( *sample,1 ),gain ) ;//q_factor + *sample = Mpy_32_32(L_shl( *sample,1 ),gain ) ;//q_factor } } } diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index ec17065ba1d5fd1a9ee402cd4a26cf01e683f4df..b3698aabe845aabc4884649ce99e649a165ef062 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1759,7 +1759,7 @@ typedef struct Word32 **channel_ptrs_fx; Word32 sampling_rate; float gain; - Word16 gain_fx; + Word32 gain_fx; float release_heuristic; Word32 release_heuristic_fx; float attack_constant; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 4b43af333869176dd10aade082ca5f80fabbed7b..078cffa7c81306bbe9ea54994aad9361860ea4b3 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -77,6 +77,7 @@ typedef float pan_vector[MAX_OUTPUT_CHANNELS]; typedef float pan_matrix[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; typedef float rotation_gains[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS]; #ifdef IVAS_FLOAT_FIXED +typedef Word32 pan_matrix_fx[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; typedef Word16 rotation_gains_fx[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS]; #endif typedef float rotation_matrix[3][3]; @@ -196,6 +197,7 @@ typedef struct { input_base base; pan_matrix hoaDecMtx; + pan_matrix_fx hoaDecMtx_fx; CREND_WRAPPER_HANDLE crendWrapper; rotation_gains rot_gains_prev; rotation_gains_fx rot_gains_prev_fx; @@ -914,18 +916,18 @@ static ivas_error initLimiter( ivas_error error; /* If re-initializing with unchanged values, return early */ - IF ( *phLimiter != NULL && ( *phLimiter )->num_channels == numChannels && ( *phLimiter )->sampling_rate == sampleRate ) + IF( *phLimiter != NULL && ( *phLimiter )->num_channels == numChannels && ( *phLimiter )->sampling_rate == sampleRate ) { return IVAS_ERR_OK; } /* Support re-init: close if already allocated */ - IF ( *phLimiter != NULL ) + IF( *phLimiter != NULL ) { ivas_limiter_close( phLimiter ); } - IF ( ( error = ivas_limiter_open( phLimiter, numChannels, sampleRate ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_limiter_open( phLimiter, numChannels, sampleRate ) ) != IVAS_ERR_OK ) { return error; } @@ -1364,7 +1366,7 @@ static ivas_error initHeadRotation( crossfade_len = L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES; tmp = 1.f / ( crossfade_len - 1 ); tmp_fx = Q31_BY_SUB_FRAME_240; - + for ( i = 0; i < crossfade_len; i++ ) { hIvasRend->headRotData.crossfade[i] = i * tmp; @@ -1372,18 +1374,18 @@ static ivas_error initHeadRotation( } /* Initialize with unit quaternions */ - FOR ( i = 0; i < hIvasRend->num_subframes; ++i ) + FOR( i = 0; i < hIvasRend->num_subframes; ++i ) { hIvasRend->headRotData.headPositions[i] = quaternionInit(); } - IF ( ( hIvasRend->headRotData.hOrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) + IF( ( hIvasRend->headRotData.hOrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" ); } - IF ( ( error = ivas_orient_trk_Init( hIvasRend->headRotData.hOrientationTracker ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_orient_trk_Init( hIvasRend->headRotData.hOrientationTracker ) ) != IVAS_ERR_OK ) { return error; } @@ -2732,7 +2734,15 @@ static ivas_error initSbaPanGainsForMcOut( #endif } } - +#ifdef IVAS_FLOAT_FIXED + for ( chOutIdx = 0; chOutIdx < MAX_OUTPUT_CHANNELS; ++chOutIdx ) + { + for ( chInIdx = 0; chInIdx < MAX_INPUT_CHANNELS; ++chInIdx ) + { + inputSba->hoaDecMtx_fx[chInIdx][chOutIdx] = (Word32)(inputSba->hoaDecMtx[chInIdx][chOutIdx] * ONE_IN_Q31); + } + } +#endif free( tmpDecMtx ); return IVAS_ERR_OK; @@ -4886,7 +4896,6 @@ ivas_error IVAS_REND_GetCombinedOrientation( /*-------------------------------------------------------------------* * Local functions *-------------------------------------------------------------------*/ - /* Take one channel from input buffer and copy it to each channel in output buffer, with different gain applied per output channel. This function takes 2 gain vectors - one for the beginning and one @@ -4958,8 +4967,110 @@ static void renderBufferChannelLerp( return; } +#ifdef IVAS_FLOAT_FIXED +/* Take one channel from input buffer and copy it to each channel + in output buffer, with different gain applied per output channel. + This function takes 2 gain vectors - one for the beginning and one + for the end of the buffer. Gain values are lineraly interpolated + for all samples in between. */ +static void renderBufferChannelLerp_fx( + const IVAS_REND_AudioBuffer inAudio, + const Word32 inChannelIdx, + const Word32 *const gainsCurrent, + const Word32 *const gainsPrev, + IVAS_REND_AudioBuffer outAudio ) +{ + const Word32 *inSmpl; + Word32 *outSmpl; + Word32 fadeIn; + Word32 fadeOut; + Word32 i; + const Word32 *lastInSmpl; + Word16 outChnlIdx; + Word32 currentGain; + Word32 previousGain; + + /* Pointer to behind last input sample */ + lastInSmpl = getSmplPtr_fx( inAudio, inChannelIdx, inAudio.config.numSamplesPerChannel ); + + FOR ( outChnlIdx = 0; outChnlIdx < outAudio.config.numChannels; ++outChnlIdx ) + { + currentGain = gainsCurrent[outChnlIdx]; + previousGain = gainsPrev == NULL ? 0 : gainsPrev[outChnlIdx]; + + /* Process current output channel only if applying non-zero gains */ + IF ( GT_32(abs( currentGain ) , EPSILON_fx) || ( gainsPrev != NULL && GT_32(abs( previousGain ) , EPSILON_fx ) )) + { + /* Reset input pointer to the beginning of input channel */ + inSmpl = getSmplPtr_fx( inAudio, inChannelIdx, 0 ); + + /* Set output pointer to first output channel sample */ + outSmpl = getSmplPtr_fx( outAudio, outChnlIdx, 0 ); + + IF ( gainsPrev == NULL || LE_32(abs( L_sub(previousGain , currentGain )) , EPSILON_fx )) + { + /* If no interpolation from previous frame, apply current gain */ + DO + { + *outSmpl = L_add(Mpy_32_32(currentGain , ( *inSmpl )),*outSmpl); + ++outSmpl; + ++inSmpl; + + } WHILE ( inSmpl != lastInSmpl ); + } + ELSE + { + i = 0; + Word32 tmp = Q31_BY_SUB_FRAME_240; + SWITCH( outAudio.config.numSamplesPerChannel ) + { + case L_SUBFRAME_48k: + tmp = Q31_BY_SUB_FRAME_240; + BREAK; + case L_SUBFRAME_32k: + tmp = Q31_BY_SUB_FRAME_180; + BREAK; + case L_SUBFRAME_16k: + tmp = Q31_BY_SUB_FRAME_80; + BREAK; + case L_SUBFRAME_8k: + tmp = Q31_BY_SUB_FRAME_40; + BREAK; + default: + BREAK; + } + /* Otherwise use weighted average between previous and current gain */ + DO + { + fadeIn = UL_Mpy_32_32( i, tmp ); + fadeOut = ONE_IN_Q31- fadeIn; + + *outSmpl = L_add(Mpy_32_32(L_add ( Mpy_32_32(fadeIn , currentGain) , Mpy_32_32(fadeOut , previousGain )) , ( *inSmpl )), *outSmpl ); + ++outSmpl; + ++inSmpl; + ++i; + } WHILE ( inSmpl != lastInSmpl ); + } + } + } + return; +} +#endif +#ifdef IVAS_FLOAT_FIXED +/* Take one channel from input buffer and copy it to each channel + in output buffer, with different gain applied per output channel */ +static void renderBufferChannel_fx( + const IVAS_REND_AudioBuffer inAudio, + const Word32 inChannelIdx, + const Word32 *const outputGains, + IVAS_REND_AudioBuffer outAudio ) +{ + renderBufferChannelLerp_fx( inAudio, inChannelIdx, outputGains, NULL, outAudio ); + return; +} +#endif /* Take one channel from input buffer and copy it to each channel in output buffer, with different gain applied per output channel */ static void renderBufferChannel( @@ -4973,7 +5084,6 @@ static void renderBufferChannel( return; } - static ivas_error chooseCrossfade( const IVAS_REND_HeadRotData *headRotData, const float **pCrossfade ) @@ -5231,7 +5341,7 @@ static ivas_error rotateFrameSba_fx( val = inAudio.data_fx[m * inAudio.config.numSamplesPerChannel + idx]; /* crossfade with previous rotation gains */ temp = Mpy_32_32( L_add( Mpy_32_16_r( cf, gains[n][m] ), ( Mpy_32_16_r( oneminuscf, gains_prev[n][m] ) ) ), val ); - tmpRot[n - m1] = L_add( L_shl(temp , 1), tmpRot[n - m1] ); // Qexp + tmpRot[n - m1] = L_add( L_shl( temp, 1 ), tmpRot[n - m1] ); // Qexp } } /* write back the result */ @@ -7220,20 +7330,29 @@ static ivas_error renderSbaToBinauralRoom( const AUDIO_CONFIG outConfig, IVAS_REND_AudioBuffer outAudio ) { - int16_t i, j; - int16_t tmp; - float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word16 i; + Word16 tmp; + Word32 tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; ivas_error error; IVAS_REND_AudioBuffer tmpRotBuffer; IVAS_REND_AudioBuffer tmpMcBuffer; IVAS_REND_AudioBuffer *tmpBufPtr; - float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; + Word32 *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData; - int8_t combinedOrientationEnabled; - int16_t subframe_idx; + Word8 combinedOrientationEnabled; + Word16 subframe_idx; tmpRotBuffer = outAudio; /* avoid compilation warning */ push_wmops( "renderSbaToBinauralRoom" ); + Word16 nchan_out; + CREND_HANDLE hCrend; + + hCrend = sbaInput->crendWrapper->hCrend; + + IF ( ( error = getAudioConfigNumChannels( outConfig, &nchan_out ) ) != IVAS_ERR_OK ) + { + return error; + } for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) { @@ -7258,107 +7377,60 @@ static ivas_error renderSbaToBinauralRoom( if ( combinedOrientationEnabled ) { tmpRotBuffer = sbaInput->base.inputBuffer; - tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); /* copy input for in-place rotation */ - mvr2r( sbaInput->base.inputBuffer.data, tmpRotBuffer.data, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel ); - for ( Word16 smpl = 0; smpl < tmpRotBuffer.config.numSamplesPerChannel; ++smpl ) - { - for ( Word16 chnl = 0; chnl < tmpRotBuffer.config.numChannels; ++chnl ) - { - tmpRotBuffer.data_fx[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl] = (Word32) float_to_fix( tmpRotBuffer.data[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl], *outAudio.pq_fact ); - } - } - - if ( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, + mvr2r_Word32( sbaInput->base.inputBuffer.data_fx, tmpRotBuffer.data_fx, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel ); + + IF( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->base.ctx.pCombinedOrientationData, sbaInput->rot_gains_prev_fx, tmpRotBuffer ) ) != IVAS_ERR_OK ) { return error; } - for ( Word16 smpl = 0; smpl < tmpRotBuffer.config.numSamplesPerChannel; ++smpl ) - { - for ( Word16 chnl = 0; chnl < tmpRotBuffer.config.numChannels; ++chnl ) - { - tmpRotBuffer.data[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl] = fix_to_float( tmpRotBuffer.data_fx[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl], *outAudio.pq_fact ); - } - } + } /* intermediate rendering to 7_1_4 */ tmpMcBuffer = sbaInput->base.inputBuffer; - if ( ( error = getAudioConfigNumChannels( IVAS_AUDIO_CONFIG_7_1_4, &tmp ) ) != IVAS_ERR_OK ) + IF ( ( error = getAudioConfigNumChannels( IVAS_AUDIO_CONFIG_7_1_4, &tmp ) ) != IVAS_ERR_OK ) { return error; } tmpMcBuffer.config.numChannels = tmp; - tmpMcBuffer.data = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( float ) ); - set_zero( tmpMcBuffer.data, tmpMcBuffer.config.numChannels * tmpMcBuffer.config.numSamplesPerChannel ); - + tmpMcBuffer.data_fx = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( Word32 ) ); + set_val_Word32( tmpMcBuffer.data_fx, 0, tmpMcBuffer.config.numChannels * tmpMcBuffer.config.numSamplesPerChannel ); tmpBufPtr = ( combinedOrientationEnabled ) ? &tmpRotBuffer : &sbaInput->base.inputBuffer; - for ( i = 0; i < sbaInput->base.inputBuffer.config.numChannels; i++ ) - { - renderBufferChannel( *tmpBufPtr, i, sbaInput->hoaDecMtx[i], tmpMcBuffer ); - } - - copyBufferTo2dArray( tmpMcBuffer, tmpCrendBuffer ); - // Porting Crend_process function - Word16 nchan_out, nchan_in; - CREND_HANDLE hCrend; - Word32 output_buffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - Word32 *output_fx[MAX_OUTPUT_CHANNELS]; - hCrend = sbaInput->crendWrapper->hCrend; - Word16 nchan; - if ( ( error = getAudioConfigNumChannels( outConfig, &nchan_out ) ) != IVAS_ERR_OK ) - { - return error; - } - nchan_in = 12; - for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + FOR ( i = 0; i < sbaInput->base.inputBuffer.config.numChannels; i++ ) { - output_fx[i] = output_buffer_fx[i]; - } - nchan = nchan_in; - for ( i = 0; i < nchan; i++ ) - { - for ( j = 0; j < L_FRAME48k; j++ ) - { - output_fx[i][j] = (Word32) float_to_fix( p_tmpCrendBuffer[i][j], *outAudio.pq_fact ); - } + renderBufferChannel_fx( *tmpBufPtr, i, sbaInput->hoaDecMtx_fx[i], tmpMcBuffer ); } + copyBufferTo2dArray_fx( tmpMcBuffer, tmpCrendBuffer ); + // Porting Crend_process function + /* call CREND */ - if ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, - NULL, NULL, NULL, NULL, output_fx, *sbaInput->base.ctx.pOutSampleRate, + IF ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, + NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ) ) ) != IVAS_ERR_OK ) { return error; } - if ( hCrend->hReverb != NULL ) + IF ( hCrend->hReverb != NULL ) { *outAudio.pq_fact -= 2; } - for ( i = 0; i < nchan_out; i++ ) - { - - for ( j = 0; j < L_FRAME48k; j++ ) - { - - p_tmpCrendBuffer[i][j] = fix_to_float( output_fx[i][j], *outAudio.pq_fact ); - } - } - accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio ); + + accumulate2dArrayToBuffer_fx( tmpCrendBuffer, &outAudio ); if ( combinedOrientationEnabled ) { - free( tmpRotBuffer.data ); free( tmpRotBuffer.data_fx ); } - free( tmpMcBuffer.data ); + free( tmpMcBuffer.data_fx ); pop_wmops(); return IVAS_ERR_OK; @@ -7487,9 +7559,6 @@ static ivas_error renderInputSba( IVAS_REND_AudioBuffer inAudio; error = IVAS_ERR_OK; inAudio = sbaInput->base.inputBuffer; - /*CREND_HANDLE hCrend; - const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData; - hCrend = sbaInput->crendWrapper->hCrend;*/ IF( NE_32( sbaInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) { @@ -8179,7 +8248,7 @@ static ivas_error getSamplesInternal( return error; } - if ( ( hIvasRend->inputsSba[0].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) && ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL ) ) + if ( ( hIvasRend->inputsSba[0].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) && ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) ) { #ifndef DISABLE_LIMITER diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 763b88d9581fad346649aae4a6ee2d58bbbe3ac2..cd34d8b88610c51e952301d748ad41eb7e9b4ce0 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -80,6 +80,7 @@ typedef struct Word16 *pq_fact; float *data; Word32 *data_fx; + Word64 *data64_fx; } IVAS_REND_AudioBuffer; #endif