From 29dcee752a90cf5f1caeb943a91428cc9613954e Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Sun, 28 Jan 2024 15:14:55 +0530 Subject: [PATCH] Completed conversion of sba to binaural renderer sample processing --- apps/renderer.c | 330 +++++++++++++++++++++++++++------------- lib_rend/ivas_limiter.c | 4 +- lib_rend/lib_rend.c | 153 ++++++++++++++----- lib_rend/lib_rend.h | 20 ++- 4 files changed, 361 insertions(+), 146 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index ea6e69ba3..dabddd8ed 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -62,7 +62,8 @@ #define IVAS_MAX16B_FLT 32767.0f #define IVAS_MIN16B_FLT ( -32768.0f ) - +#define IVAS_MAX16B_FX 32767 +#define IVAS_MIN16B_FX ( -32768 ) #if !defined( WMOPS ) static #endif @@ -161,7 +162,7 @@ typedef struct bool sceneDescriptionInput; float inputGainGlobal; /* Linear gain (not in dB) */ bool lfePanningEnabled; - float lfeConfigGain; /* Linear gain (not in dB) */ + float lfeConfigGain; /* Linear gain (not in dB) */ float lfeConfigAzimuth; float lfeConfigElevation; bool lfeCustomRoutingEnabled; @@ -404,12 +405,46 @@ static IVAS_AUDIO_CONFIG parseAudioConfig( const char *configString ); static void convertInputBuffer( const int16_t *intBuffer, const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, float *floatBuffer ); static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, int16_t *intBuffer ); +#ifdef IVAS_FLOAT_FIXED +static void convertOutputBuffer_fx( const Word32 *Word32Buffer, const Word16 numSamplesPerChannel, const Word16 numChannels, Word16 *intBuffer,Word16 q_factor ); +static void convertInputBuffer_fx( const Word16 *intBuffer, const Word16 numIntSamplesPerChannel, const Word16 numFloatSamplesPerChannel, const Word16 numChannels, Word32 *Int32Buffer,Word16 in_q_factor ); +#endif /*------------------------------------------------------------------------------------------* * Local functions *------------------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +// The function is defined inside library files too with different nsme but same functionality +static Word16 find_guard_bits( Word32 n ) +{ + return n <= 1 ? 0 : n <= 2 ? 1 + : n <= 4 ? 2 + : n <= 8 ? 3 + : n <= 16 ? 4 + : n <= 32 ? 5 + : n <= 64 ? 6 + : n <= 128 ? 7 + : n <= 256 ? 8 + : n <= 512 ? 9 + : n <= 1024 ? 10 + : 11; +} +static IVAS_REND_ReadOnlyAudioBuffer getReadOnlySubBuffer( + IVAS_REND_AudioBuffer buffer, + const Word16 chBeginIdx, + const Word16 numChannels ) +{ + IVAS_REND_ReadOnlyAudioBuffer subBuffer; + subBuffer.config = buffer.config; + subBuffer.config.numChannels = numChannels; + subBuffer.data = buffer.data + subBuffer.config.numSamplesPerChannel * chBeginIdx; + subBuffer.data_fx = buffer.data_fx + subBuffer.config.numSamplesPerChannel * chBeginIdx; + + return subBuffer; +} +#else static IVAS_REND_ReadOnlyAudioBuffer getReadOnlySubBuffer( IVAS_REND_AudioBuffer buffer, const int16_t chBeginIdx, @@ -423,15 +458,14 @@ static IVAS_REND_ReadOnlyAudioBuffer getReadOnlySubBuffer( return subBuffer; } - +#endif static int16_t getTotalNumInChannels( IVAS_REND_HANDLE hIvasRend, IVAS_REND_InputId mcIds[RENDERER_MAX_MC_INPUTS], IVAS_REND_InputId ismIds[RENDERER_MAX_ISM_INPUTS], IVAS_REND_InputId sbaIds[RENDERER_MAX_SBA_INPUTS], - IVAS_REND_InputId masaIds[RENDERER_MAX_MASA_INPUTS] -) + IVAS_REND_InputId masaIds[RENDERER_MAX_MASA_INPUTS] ) { int16_t totalNumInChannels = 0; int16_t i, numInputChannels; @@ -517,8 +551,7 @@ static void setupWithSingleFormatInput( CmdlnArgs args, char *audioFilePath, IsmPositionProvider *positionProvider, - MasaFileReader **masaReaders -) + MasaFileReader **masaReaders ) { /* With single-format input, inputFilePath is the path to input audio file. */ strncpy( audioFilePath, args.inputFilePath, FILENAME_MAX - 1 ); @@ -577,8 +610,6 @@ static float dBToLin( } - - /*------------------------------------------------------------------------------------------* * main() * @@ -611,6 +642,7 @@ int main( int16_t *outInt16Buffer; #ifdef IVAS_FLOAT_FIXED Word32 *outInt32Buffer; + Word32 *inInt32Buffer; #endif float *outFloatBuffer; IVAS_REND_AudioBuffer inBuffer; @@ -749,14 +781,14 @@ int main( } } - if ( AudioFileReader_open( &audioReader, audioFilePath ) != IVAS_ERR_OK ) - { - fprintf( stderr, "Error opening file: %s\n", audioFilePath ); - exit( -1 ); - } + if ( AudioFileReader_open( &audioReader, audioFilePath ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", audioFilePath ); + exit( -1 ); + } int32_t inFileSampleRate = 0; - error = AudioFileReader_getSamplingRate( audioReader, &inFileSampleRate ); + error = AudioFileReader_getSamplingRate( audioReader, &inFileSampleRate ); switch ( error ) { @@ -786,12 +818,12 @@ int main( } int16_t inFileNumChannels = 0; - error = AudioFileReader_getNumChannels( audioReader, &inFileNumChannels ); - if ( error != IVAS_ERR_OK && error != IVAS_ERR_NUM_CHANNELS_UNKNOWN ) - { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); - } + error = AudioFileReader_getNumChannels( audioReader, &inFileNumChannels ); + if ( error != IVAS_ERR_OK && error != IVAS_ERR_NUM_CHANNELS_UNKNOWN ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } const int16_t frameSize_smpls = (int16_t) ( ( args.render_framesize ) * args.sampleRate * 5 / ( 1000 ) ); if ( ( error = IVAS_REND_Open( &hIvasRend, args.sampleRate, args.outConfig.audioConfig, args.nonDiegeticPan, args.nonDiegeticPanGain, (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) @@ -855,7 +887,6 @@ int main( fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed\n" ); exit( -1 ); } - } if ( ( error = IVAS_REND_SetOrientationTrackingMode( hIvasRend, args.orientation_tracking ) ) != IVAS_ERR_OK ) @@ -1091,11 +1122,11 @@ int main( } - if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) - { - fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); - exit( -1 ); - } + if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); + exit( -1 ); + } inBufferSize = frameSize_smpls * totalNumInChannels; outBufferSize = frameSize_smpls * numOutChannels; @@ -1105,6 +1136,7 @@ int main( outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); #ifdef IVAS_FLOAT_FIXED outInt32Buffer = malloc( outBufferSize * sizeof( Word32 ) ); + inInt32Buffer = malloc( inBufferSize * sizeof( Word32 ) ); #endif outFloatBuffer = malloc( outBufferSize * sizeof( float ) ); @@ -1117,6 +1149,7 @@ int main( outBuffer.data = outFloatBuffer; #ifdef IVAS_FLOAT_FIXED outBuffer.data_fx = outInt32Buffer; + inBuffer.data_fx = inInt32Buffer; #endif #ifdef WMOPS reset_stack(); @@ -1134,19 +1167,23 @@ int main( } ObjectPositionBuffer mtdBuffer; - +#ifdef IVAS_FLOAT_FIXED + outBuffer.pq_fact = &outBuffer.q_factor; + Word16 subframe_len = (Word16) ( args.sampleRate / ( 200 ) ); // sample rate /FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES + Word16 gd_bits = find_guard_bits( subframe_len ); +#endif while ( 1 ) { int16_t num_in_channels; num_in_channels = inBuffer.config.numChannels; const bool isCurrentFrameMultipleOf20ms = frame % ( 4 / args.render_framesize ) == 0; - /* Read the input data */ - if ( ( error = AudioFileReader_read( audioReader, inpInt16Buffer, (int16_t) inBufferSize, &numSamplesRead ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError reading from file %s\n", audioFilePath ); - exit( -1 ); - } + /* Read the input data */ + if ( ( error = AudioFileReader_read( audioReader, inpInt16Buffer, (int16_t) inBufferSize, &numSamplesRead ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError reading from file %s\n", audioFilePath ); + exit( -1 ); + } if ( numSamplesRead == 0 && splitBinNeedsNewFrame ) { @@ -1156,7 +1193,10 @@ 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 ); + convertInputBuffer_fx( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inInt32Buffer, *outBuffer.pq_fact ); +#endif int16_t num_subframes, sf_idx; num_subframes = (int16_t) args.render_framesize; @@ -1327,12 +1367,13 @@ int main( exit( -1 ); } IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.ambisonicsBuses[i].inputChannelIndex, numChannels ); - - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, sbaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) +#ifdef IVAS_FLOAT_FIXED + if ( ( error = IVAS_REND_FeedInputAudio_fx( hIvasRend, sbaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); } +#endif } for ( i = 0; i < args.inConfig.numMasaBuses; ++i ) @@ -1370,21 +1411,28 @@ int main( } } - - - if ( ( error = IVAS_REND_GetSamples( hIvasRend, outBuffer ) ) != IVAS_ERR_OK ) - { + if ( ( error = IVAS_REND_GetSamples( hIvasRend, outBuffer ) ) != IVAS_ERR_OK ) + { fprintf( stderr, "Error in getting samples\n" ); - exit( -1 ); - } + exit( -1 ); + } int16_t num_out_channels; num_out_channels = outBuffer.config.numChannels; - +#ifdef IVAS_FLOAT_FIXED /* Convert from float to int and from packed to interleaved. * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ - convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); - + if ( *outBuffer.pq_fact == 0 ) + { +#endif + convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); +#ifdef IVAS_FLOAT_FIXED + } + else + { + convertOutputBuffer_fx( outInt32Buffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, *outBuffer.pq_fact ); + } +#endif if ( delayNumSamples == -1 ) { if ( args.delayCompensationEnabled ) @@ -1405,19 +1453,19 @@ int main( zeroPad = delayNumSamples; } - if ( delayNumSamples * num_out_channels < outBufferSize ) - { - if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "Error writing audio file %s\n", args.outputFilePath ); - exit( -1 ); - } - delayNumSamples = 0; - } - else + if ( delayNumSamples * num_out_channels < outBufferSize ) + { + if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) { - delayNumSamples -= (int16_t) ( outBufferSize / num_out_channels ); + fprintf( stderr, "Error writing audio file %s\n", args.outputFilePath ); + exit( -1 ); } + delayNumSamples = 0; + } + else + { + delayNumSamples -= (int16_t) ( outBufferSize / num_out_channels ); + } /* Write MASA metadata for MASA outputs */ if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA1 || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) @@ -1522,23 +1570,23 @@ int main( } /* add zeros at the end to have equal length of synthesized signals */ - for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) - { - memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); - if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nOutput audio file writer error\n" ); - exit( -1 ); - } - } - - memset( outInt16Buffer, 0, zeroPadToWrite * outBuffer.config.numChannels * sizeof( int16_t ) ); - if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) + for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) + { + memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); exit( -1 ); } - zeroPadToWrite = 0; + } + + memset( outInt16Buffer, 0, zeroPadToWrite * outBuffer.config.numChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + exit( -1 ); + } + zeroPadToWrite = 0; if ( args.inConfig.numAudioObjects != 0 && ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) @@ -1561,6 +1609,7 @@ int main( free( outFloatBuffer ); #ifdef IVAS_FLOAT_FIXED free( outInt32Buffer ); + free( inInt32Buffer ); #endif for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) { @@ -3251,7 +3300,6 @@ static ivas_error parseLfePanMtxFile( return IVAS_ERR_OK; } - /*--------------------------------------------------------------------------* * convertInputBuffer() * @@ -3264,73 +3312,149 @@ static void convertInputBuffer( const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, - float *floatBuffer -) + float *floatBuffer ) { int16_t chnl, smpl, i; i = 0; - for ( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) + for ( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) { - for ( chnl = 0; chnl < numChannels; ++chnl ) + if ( i < numIntSamplesPerChannel ) { - if ( i < numIntSamplesPerChannel ) - { - floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = (float) intBuffer[i]; - } - else - { - floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = 0.f; - } + floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = (float) intBuffer[i]; + } + else + { + floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = 0.f; + } - ++i; + ++i; + } + } + + return; +} +#ifdef IVAS_FLOAT_FIXED + +/*--------------------------------------------------------------------------* + * convertInputBuffer() + * + * Convert input buffer from WAV/PCM file (int16_t, interleaved) to a format + * accepted by the renderer (float, packed) + *--------------------------------------------------------------------------*/ + +static void convertInputBuffer_fx( + const Word16 *intBuffer, + const Word16 numIntSamplesPerChannel, + const Word16 numFloatSamplesPerChannel, + const Word16 numChannels, + Word32 *Word32Buffer, + Word16 in_q_factor) +{ + Word16 chnl, smpl, i; + + i = 0; + + FOR ( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) + { + FOR ( chnl = 0; chnl < numChannels; ++chnl ) + { + IF ( i < numIntSamplesPerChannel ) + { + Word32Buffer[chnl * numFloatSamplesPerChannel + smpl] = L_shl( (Word32) intBuffer[i], in_q_factor ); } + ELSE + { + Word32Buffer[chnl * numFloatSamplesPerChannel + smpl] = 0; + } + + ++i; } + } return; } +/*--------------------------------------------------------------------------* + * convertOutputBuffer() + * + * Convert output buffer from the renderer (Word32, packed) to a format ready + * for writing to a WAV/PCM file (Word16, interleaved) + *--------------------------------------------------------------------------*/ +static void convertOutputBuffer_fx( + const Word32 *Word32Buffer, + const Word16 numSamplesPerChannel, + const Word16 numChannels, + Word16 *intBuffer, + Word16 out_q ) +{ + Word16 chnl, smpl, i; + Word32 temp_fx; + Word32 temp_fx1; + i = 0; + FOR ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) + { + FOR ( chnl = 0; chnl < numChannels; ++chnl ) + { + temp_fx = L_add( Word32Buffer[chnl * numSamplesPerChannel + smpl], lshl( 1, ( out_q - 1 ) ) ); + temp_fx1 = L_shr(temp_fx , out_q); + IF (GT_32( temp_fx1, IVAS_MAX16B_FX )) + { + temp_fx1 = IVAS_MAX16B_FX; + } + ELSE IF ( LT_32(temp_fx1 , IVAS_MIN16B_FX )) + { + temp_fx1 = IVAS_MIN16B_FX; + } + intBuffer[i] = (Word16) temp_fx1; + + ++i; + } + } + + return; +} +#endif /*--------------------------------------------------------------------------* * convertOutputBuffer() * * Convert output buffer from the renderer (float, packed) to a format ready * for writing to a WAV/PCM file (int16_t, interleaved) *--------------------------------------------------------------------------*/ - static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, - int16_t *intBuffer -) + int16_t *intBuffer ) { int16_t chnl, smpl, i; float temp; i = 0; - for ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) + for ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) { - for ( chnl = 0; chnl < numChannels; ++chnl ) + temp = floatBuffer[chnl * numSamplesPerChannel + smpl]; + temp = (float) floor( temp + 0.5f ); + if ( temp > IVAS_MAX16B_FLT ) { - temp = floatBuffer[chnl * numSamplesPerChannel + smpl]; - temp = (float) floor( temp + 0.5f ); - if ( temp > IVAS_MAX16B_FLT ) - { - temp = IVAS_MAX16B_FLT; - } - else if ( temp < IVAS_MIN16B_FLT ) - { - temp = IVAS_MIN16B_FLT; - } - intBuffer[i] = (int16_t) temp; - - ++i; + temp = IVAS_MAX16B_FLT; } + else if ( temp < IVAS_MIN16B_FLT ) + { + temp = IVAS_MIN16B_FLT; + } + intBuffer[i] = (int16_t) temp; + + ++i; } + } return; } - #undef WMC_TOOL_SKIP diff --git a/lib_rend/ivas_limiter.c b/lib_rend/ivas_limiter.c index 5d540c7d3..269311ffd 100644 --- a/lib_rend/ivas_limiter.c +++ b/lib_rend/ivas_limiter.c @@ -494,10 +494,10 @@ void limiter_process_fx( /*For powf(200.0f,x)*/ fact = L_Extract_lc( mul, &exp_pow ); result = extract_l( Pow2( 14, fact ) ); - div32 = divide3232( L_lshl( 1, ( 14 - exp_pow + 1 ) ), L_mult( result, sample_num ) ); + 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_lshl( -div32, fact_2 ), &exp_pow_2 ); + release_constant = pow_10( L_shl( -div32, fact_2 ), &exp_pow_2 ); /* 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 ) ); diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 7b8520468..4ab880f61 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -224,7 +224,33 @@ typedef struct MASA_EXT_REND_HANDLE hMasaExtRend; MASA_PREREND_HANDLE hMasaPrerend; } input_masa; +#ifdef IVAS_FLOAT_FIXED +struct IVAS_REND +{ + Word32 sampleRateOut; + IVAS_LIMITER_HANDLE hLimiter; + + input_ism inputsIsm[RENDERER_MAX_ISM_INPUTS]; + input_mc inputsMc[RENDERER_MAX_MC_INPUTS]; + input_sba inputsSba[RENDERER_MAX_SBA_INPUTS]; + input_masa inputsMasa[RENDERER_MAX_MASA_INPUTS]; + + AUDIO_CONFIG inputConfig; + AUDIO_CONFIG outputConfig; + EFAP_WRAPPER efapOutWrapper; + IVAS_LSSETUP_CUSTOM_STRUCT customLsOut; + + IVAS_REND_HeadRotData headRotData; + EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData; + COMBINED_ORIENTATION_HANDLE hCombinedOrientationData; + + Word8 rendererConfigEnabled; + RENDER_CONFIG_DATA *hRendererConfig; /* Renderer config pointer */ + + Word16 num_subframes; +}; +#else struct IVAS_REND { int32_t sampleRateOut; @@ -251,7 +277,7 @@ struct IVAS_REND int16_t num_subframes; }; - +#endif /*-------------------------------------------------------------------* * Local function prototypes @@ -464,7 +490,7 @@ static Word32 limitRendererOutput_fx( Word32 numClipping = 0; /* return early if given bad parameters */ - IF ( hLimiter == NULL || output == NULL || output_frame <= 0 ) + IF( hLimiter == NULL || output == NULL || output_frame <= 0 ) { return 0; } @@ -472,7 +498,7 @@ static Word32 limitRendererOutput_fx( channels = hLimiter->channel_ptrs_fx; num_channels = hLimiter->num_channels; - FOR ( i = 0; i < num_channels; ++i ) + FOR( i = 0; i < num_channels; ++i ) { channels[i] = output + i * output_frame; } @@ -480,10 +506,10 @@ static Word32 limitRendererOutput_fx( limiter_process_fx( hLimiter, output_frame, threshold, 0, NULL, q_factor ); /* Apply clipping to buffer in case the limiter let through some samples > 1.0f */ - FOR ( i = 0; i < output_frame * num_channels; ++i ) + FOR( i = 0; i < output_frame * num_channels; ++i ) { - output[i] = min( max( L_lshl( INT16_MIN, q_factor ), output[i] ), L_lshl( INT16_MAX, q_factor ) ); + output[i] = min( max( L_shl( INT16_MIN, q_factor ), output[i] ), L_shl( INT16_MAX, q_factor ) ); } return numClipping; @@ -4029,7 +4055,75 @@ ivas_error IVAS_REND_GetDelay( return IVAS_ERR_OK; } +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * IVAS_REND_FeedInputAudio() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_FeedInputAudio_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ +) +{ + ivas_error error; + input_base *inputBase; + int16_t numInputChannels; + + /* Validate function arguments */ + if ( hIvasRend == NULL || inputAudio.data == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( inputAudio.config.numSamplesPerChannel <= 0 || MAX_BUFFER_LENGTH_PER_CHANNEL < inputAudio.config.numSamplesPerChannel ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Buffer size outside of supported range" ); + } + + if ( inputAudio.config.numChannels <= 0 || MAX_INPUT_CHANNELS < inputAudio.config.numChannels ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && + inputAudio.config.numSamplesPerChannel * 1000 != ( BINAURAL_RENDERING_FRAME_SIZE_MS * hIvasRend->num_subframes ) * hIvasRend->sampleRateOut ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Binaural rendering requires specific frame size" ); + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = getRendInputNumChannels( inputBase, &numInputChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_MASA1 || hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_MASA2 ) && inputBase->inConfig == IVAS_AUDIO_CONFIG_OBA ) + { + numInputChannels = (int16_t) hIvasRend->inputsIsm[0].total_num_objects; + } + + if ( numInputChannels != inputAudio.config.numChannels ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + inputBase->inputBuffer.config = inputAudio.config; + + mvr2r( inputAudio.data, inputBase->inputBuffer.data, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); + mvr2r_Word32( inputAudio.data_fx, inputBase->inputBuffer.data_fx, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); + + inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel; + + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------* * IVAS_REND_FeedInputAudio() * @@ -4955,7 +5049,6 @@ static ivas_error rotateFrameSba_fx( for ( l = 0; l < 3; l++ ) { Rmat[i][l] = ( *hCombinedOrientationData )->Rmat_fx[subframe_idx][i][l]; // Q30 - } } else @@ -6884,10 +6977,9 @@ static ivas_error renderSbaToBinaural( } IF( hCrend->hReverb != NULL ) { - *outAudio.q_fact -= 2; + *outAudio.pq_fact -= 2; } accumulate2dArrayToBuffer_fx( output_buffer_fx, &outAudio ); - } pop_wmops(); @@ -7020,7 +7112,7 @@ static ivas_error renderSbaToBinauralRoom( { 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.q_fact ); + tmpRotBuffer.data_fx[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl] = (Word32) float_to_fix( tmpRotBuffer.data[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl], *outAudio.pq_fact ); } } @@ -7035,7 +7127,7 @@ static ivas_error renderSbaToBinauralRoom( { 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.q_fact ); + tmpRotBuffer.data[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl] = fix_to_float( tmpRotBuffer.data_fx[chnl * tmpRotBuffer.config.numSamplesPerChannel + smpl], *outAudio.pq_fact ); } } } @@ -7081,7 +7173,7 @@ static ivas_error renderSbaToBinauralRoom( { for ( j = 0; j < L_FRAME48k; j++ ) { - output_fx[i][j] = (Word32) float_to_fix( p_tmpCrendBuffer[i][j], *outAudio.q_fact ); + output_fx[i][j] = (Word32) float_to_fix( p_tmpCrendBuffer[i][j], *outAudio.pq_fact ); } } /* call CREND */ @@ -7093,7 +7185,7 @@ static ivas_error renderSbaToBinauralRoom( } if ( hCrend->hReverb != NULL ) { - *outAudio.q_fact -= 2; + *outAudio.pq_fact -= 2; } for ( i = 0; i < nchan_out; i++ ) { @@ -7101,7 +7193,7 @@ static ivas_error renderSbaToBinauralRoom( for ( j = 0; j < L_FRAME48k; j++ ) { - p_tmpCrendBuffer[i][j] = fix_to_float( output_fx[i][j], *outAudio.q_fact ); + p_tmpCrendBuffer[i][j] = fix_to_float( output_fx[i][j], *outAudio.pq_fact ); } } accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio ); @@ -7252,7 +7344,7 @@ static ivas_error renderInputSba( /* Apply input gain to new audio */ v_multc_fixed( inAudio.data_fx, sbaInput->base.gain_fx, inAudio.data_fx, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); - *outAudio.q_fact -= 1; // to compensate for the qfactor reduction in gain multiplication. + *outAudio.pq_fact -= 1; // to compensate for the qfactor reduction in gain multiplication. /* set combined orientation subframe info to start info */ ivas_combined_orientation_set_to_start_index( *( sbaInput->base.ctx.pCombinedOrientationData ) ); @@ -7352,15 +7444,15 @@ static ivas_error renderActiveInputsSba( Word16 i; input_sba *pCurrentInput; ivas_error error; - + for ( i = 0, pCurrentInput = hIvasRend->inputsSba; i < RENDERER_MAX_SBA_INPUTS; ++i, ++pCurrentInput ) { - IF ( pCurrentInput->base.inConfig == IVAS_AUDIO_CONFIG_INVALID ) + IF( pCurrentInput->base.inConfig == IVAS_AUDIO_CONFIG_INVALID ) { /* Skip inactive inputs */ CONTINUE; } - IF ( ( error = renderInputSba( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) + IF( ( error = renderInputSba( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) { return error; } @@ -7847,22 +7939,6 @@ static ivas_error getSamplesInternal( { ivas_error error; int16_t numOutChannels; - Word16 subframe_len, gd_bits,j; - if ( hIvasRend->inputsSba[0].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) - { - subframe_len = (Word16) ( *hIvasRend->inputsSba->base.ctx.pOutSampleRate / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ); - gd_bits = find_guarded_bits_fx( subframe_len ); - outAudio.q_fact = &outAudio.q_factor; - *outAudio.q_fact = 16; - *outAudio.q_fact -= gd_bits + 1; - for ( Word16 smpl = 0; smpl < hIvasRend->inputsSba->base.inputBuffer.config.numSamplesPerChannel; ++smpl ) - { - for ( Word16 chnl = 0; chnl < hIvasRend->inputsSba->base.inputBuffer.config.numChannels; ++chnl ) - { - hIvasRend->inputsSba->base.inputBuffer.data_fx[chnl * hIvasRend->inputsSba->base.inputBuffer.config.numSamplesPerChannel + smpl] = (Word32) float_to_fix( hIvasRend->inputsSba->base.inputBuffer.data[chnl * hIvasRend->inputsSba->base.inputBuffer.config.numSamplesPerChannel + smpl], *outAudio.q_fact ); - } - } - } /* Validate function arguments */ if ( hIvasRend == NULL || outAudio.data == NULL ) { @@ -7952,13 +8028,13 @@ static ivas_error getSamplesInternal( { #ifndef DISABLE_LIMITER - Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.q_fact ); - limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.q_fact ); - for ( j = 0; j < outAudio.config.numChannels * outAudio.config.numSamplesPerChannel; j++ ) + Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact ); + limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.pq_fact ); + /* for ( j = 0; j < outAudio.config.numChannels * outAudio.config.numSamplesPerChannel; j++ ) { - outAudio.data[j] = fix_to_float( outAudio.data_fx[j], *outAudio.q_fact ); + outAudio.data[j] = fix_to_float( outAudio.data_fx[j], *outAudio.q_fact ); } - +*/ #endif } else @@ -7966,6 +8042,7 @@ static ivas_error getSamplesInternal( #ifndef DISABLE_LIMITER limitRendererOutput( hIvasRend->hLimiter, outAudio.data, outAudio.config.numSamplesPerChannel, IVAS_LIMITER_THRESHOLD ); #endif + *outAudio.pq_fact = 0; } /* update global cominbed orientation start index */ diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index cd6cd029d..763b88d95 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -77,20 +77,27 @@ typedef struct { IVAS_REND_AudioBufferConfig config; Word16 q_factor; - Word16 *q_fact; + Word16 *pq_fact; float *data; Word32 *data_fx; } IVAS_REND_AudioBuffer; #endif - +#ifdef IVAS_FLOAT_FIXED typedef struct { IVAS_REND_AudioBufferConfig config; const float *data; + const Word32 *data_fx; } IVAS_REND_ReadOnlyAudioBuffer; - +#else +typedef struct +{ + IVAS_REND_AudioBufferConfig config; + const float *data; +} IVAS_REND_ReadOnlyAudioBuffer; +#endif typedef struct IVAS_REND *IVAS_REND_HANDLE; typedef struct IVAS_REND const *IVAS_REND_CONST_HANDLE; @@ -201,7 +208,14 @@ ivas_error IVAS_REND_FeedInputAudio( const IVAS_REND_InputId inputId, /* i : ID of the input */ const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ ); +#ifdef IVAS_FLOAT_FIXED +ivas_error IVAS_REND_FeedInputAudio_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ +); +#endif ivas_error IVAS_REND_FeedInputObjectMetadata( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_REND_InputId inputId, /* i : ID of the input */ -- GitLab