diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/codec.h b/webrtc/modules/audio_coding/codecs/isac/main/source/codec.h index b7319b9ec..4b36fffed 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/codec.h +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/codec.h @@ -31,16 +31,20 @@ int WebRtcIsac_EstimateBandwidth(BwEstimatorstr* bwest_str, Bitstr* streamdata, enum IsacSamplingRate encoderSampRate, enum IsacSamplingRate decoderSampRate); -int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdec_obj, +int WebRtcIsac_DecodeLb(const TransformTables* transform_tables, + float* signal_out, + ISACLBDecStruct* ISACdec_obj, int16_t* current_framesamples, int16_t isRCUPayload); int WebRtcIsac_DecodeRcuLb(float* signal_out, ISACLBDecStruct* ISACdec_obj, int16_t* current_framesamples); -int WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj, - int16_t codingMode, int16_t - bottleneckIndex); +int WebRtcIsac_EncodeLb(const TransformTables* transform_tables, + float* in, + ISACLBEncStruct* ISACencLB_obj, + int16_t codingMode, + int16_t bottleneckIndex); int WebRtcIsac_EncodeStoredDataLb(const IsacSaveEncoderData* ISACSavedEnc_obj, Bitstr* ISACBitStr_obj, int BWnumber, @@ -93,10 +97,11 @@ int16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec, * Return value : >0 number of decoded bytes. * <0 if an error occurred. */ -int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdec_obj, +int WebRtcIsac_DecodeUb16(const TransformTables* transform_tables, + float* signal_out, + ISACUBDecStruct* ISACdec_obj, int16_t isRCUPayload); - /****************************************************************************** * WebRtcIsac_DecodeUb12() * @@ -112,10 +117,11 @@ int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdec_obj, * Return value : >0 number of decoded bytes. * <0 if an error occurred. */ -int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdec_obj, +int WebRtcIsac_DecodeUb12(const TransformTables* transform_tables, + float* signal_out, + ISACUBDecStruct* ISACdec_obj, int16_t isRCUPayload); - /****************************************************************************** * WebRtcIsac_EncodeUb16() * @@ -131,10 +137,11 @@ int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdec_obj, * Return value : >0 number of encoded bytes. * <0 if an error occurred. */ -int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACenc_obj, +int WebRtcIsac_EncodeUb16(const TransformTables* transform_tables, + float* in, + ISACUBEncStruct* ISACenc_obj, int32_t jitterInfo); - /****************************************************************************** * WebRtcIsac_EncodeUb12() * @@ -150,7 +157,9 @@ int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACenc_obj, * Return value : >0 number of encoded bytes. * <0 if an error occurred. */ -int WebRtcIsac_EncodeUb12(float* in, ISACUBEncStruct* ISACenc_obj, +int WebRtcIsac_EncodeUb12(const TransformTables* transform_tables, + float* in, + ISACUBEncStruct* ISACenc_obj, int32_t jitterInfo); /************************** initialization functions *************************/ @@ -168,14 +177,21 @@ void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct* State); /**************************** transform functions ****************************/ -void WebRtcIsac_InitTransform(); +void WebRtcIsac_InitTransform(TransformTables* tables); -void WebRtcIsac_Time2Spec(double* inre1, double* inre2, int16_t* outre, - int16_t* outim, FFTstr* fftstr_obj); - -void WebRtcIsac_Spec2time(double* inre, double* inim, double* outre1, - double* outre2, FFTstr* fftstr_obj); +void WebRtcIsac_Time2Spec(const TransformTables* tables, + double* inre1, + double* inre2, + int16_t* outre, + int16_t* outim, + FFTstr* fftstr_obj); +void WebRtcIsac_Spec2time(const TransformTables* tables, + double* inre, + double* inim, + double* outre1, + double* outre2, + FFTstr* fftstr_obj); /******************************* filter functions ****************************/ diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/decode.c b/webrtc/modules/audio_coding/codecs/isac/main/source/decode.c index e23765bbb..e925efba6 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/decode.c +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/decode.c @@ -35,7 +35,8 @@ * function to decode the bitstream * returns the total number of bytes in the stream */ -int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdecLB_obj, +int WebRtcIsac_DecodeLb(const TransformTables* transform_tables, + float* signal_out, ISACLBDecStruct* ISACdecLB_obj, int16_t* current_framesamples, int16_t isRCUPayload) { int k; @@ -122,7 +123,7 @@ int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdecLB_obj, } /* Inverse transform. */ - WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw, + WebRtcIsac_Spec2time(transform_tables, real_f, imag_f, LPw, HPw, &ISACdecLB_obj->fftstr_obj); /* Convert PitchGains back to float for pitchfilter_post */ @@ -181,7 +182,8 @@ int WebRtcIsac_DecodeLb(float* signal_out, ISACLBDecStruct* ISACdecLB_obj, * Contrary to lower-band, the upper-band (8-16 kHz) is not split in * frequency, but split to 12 sub-frames, i.e. twice as lower-band. */ -int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdecUB_obj, +int WebRtcIsac_DecodeUb16(const TransformTables* transform_tables, + float* signal_out, ISACUBDecStruct* ISACdecUB_obj, int16_t isRCUPayload) { int len, err; @@ -218,7 +220,8 @@ int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdecUB_obj, } } /* Inverse transform. */ - WebRtcIsac_Spec2time(real_f, imag_f, halfFrameFirst, halfFrameSecond, + WebRtcIsac_Spec2time(transform_tables, + real_f, imag_f, halfFrameFirst, halfFrameSecond, &ISACdecUB_obj->fftstr_obj); /* Perceptual post-filtering (using normalized lattice filter). */ @@ -245,8 +248,9 @@ int WebRtcIsac_DecodeUb16(float* signal_out, ISACUBDecStruct* ISACdecUB_obj, * reconstructed and 12-16 kHz replaced with zeros. Then two bands * are combined, to reconstruct the upperband 8-16 kHz. */ -int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdecUB_obj, - int16_t isRCUPayload) { +int WebRtcIsac_DecodeUb12(const TransformTables* transform_tables, + float* signal_out, ISACUBDecStruct* ISACdecUB_obj, + int16_t isRCUPayload) { int len, err; float LP_dec_float[FRAMESAMPLES_HALF]; @@ -284,7 +288,8 @@ int WebRtcIsac_DecodeUb12(float* signal_out, ISACUBDecStruct* ISACdecUB_obj, } } /* Inverse transform. */ - WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj); + WebRtcIsac_Spec2time(transform_tables, + real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj); /* perceptual post-filtering (using normalized lattice filter) */ WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER, ISACdecUB_obj->maskfiltstr_obj.PostStateLoF, diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/encode.c b/webrtc/modules/audio_coding/codecs/isac/main/source/encode.c index a089f72cd..3f1912b6d 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/encode.c +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/encode.c @@ -177,7 +177,8 @@ void WebRtcIsac_ResetBitstream(Bitstr* bit_stream) { bit_stream->streamval = 0; } -int WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj, +int WebRtcIsac_EncodeLb(const TransformTables* transform_tables, + float* in, ISACLBEncStruct* ISACencLB_obj, int16_t codingMode, int16_t bottleneckIndex) { int stream_length = 0; @@ -382,7 +383,8 @@ int WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj, WebRtcIsac_PitchfilterPre(LPw, LPw_pf, &ISACencLB_obj->pitchfiltstr_obj, PitchLags, PitchGains); /* Transform */ - WebRtcIsac_Time2Spec(LPw_pf, HPw, fre, fim, &ISACencLB_obj->fftstr_obj); + WebRtcIsac_Time2Spec(transform_tables, + LPw_pf, HPw, fre, fim, &ISACencLB_obj->fftstr_obj); /* Save data for multiple packets memory. */ my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF; @@ -641,7 +643,8 @@ static int LimitPayloadUb(ISACUBEncStruct* ISACencUB_obj, return 0; } -int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACencUB_obj, +int WebRtcIsac_EncodeUb16(const TransformTables* transform_tables, + float* in, ISACUBEncStruct* ISACencUB_obj, int32_t jitterInfo) { int err; int k; @@ -782,7 +785,8 @@ int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACencUB_obj, &percepFilterParams[(UB_LPC_ORDER + 1) + SUBFRAMES * (UB_LPC_ORDER + 1)], &LP_lookahead[FRAMESAMPLES_HALF]); - WebRtcIsac_Time2Spec(&LP_lookahead[0], &LP_lookahead[FRAMESAMPLES_HALF], + WebRtcIsac_Time2Spec(transform_tables, + &LP_lookahead[0], &LP_lookahead[FRAMESAMPLES_HALF], fre, fim, &ISACencUB_obj->fftstr_obj); /* Store FFT coefficients for multiple encoding. */ @@ -826,7 +830,8 @@ int WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACencUB_obj, } -int WebRtcIsac_EncodeUb12(float* in, ISACUBEncStruct* ISACencUB_obj, +int WebRtcIsac_EncodeUb12(const TransformTables* transform_tables, + float* in, ISACUBEncStruct* ISACencUB_obj, int32_t jitterInfo) { int err; int k; @@ -957,7 +962,8 @@ int WebRtcIsac_EncodeUb12(float* in, ISACUBEncStruct* ISACencUB_obj, memset(HPw, 0, sizeof(HPw)); /* Transform */ - WebRtcIsac_Time2Spec(LPw, HPw, fre, fim, &ISACencUB_obj->fftstr_obj); + WebRtcIsac_Time2Spec(transform_tables, + LPw, HPw, fre, fim, &ISACencUB_obj->fftstr_obj); /* Store FFT coefficients for multiple encoding. */ memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre, diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/intialize.c b/webrtc/modules/audio_coding/codecs/isac/main/source/intialize.c index 6df034d1c..01e683c57 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/intialize.c +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/intialize.c @@ -40,10 +40,6 @@ void WebRtcIsac_InitMasking(MaskFiltstr *maskdata) { } maskdata->OldEnergy = 10.0; - - /* fill tables for transforms */ - WebRtcIsac_InitTransform(); - return; } diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/isac.c b/webrtc/modules/audio_coding/codecs/isac/main/source/isac.c index 963270e7e..6a91757ad 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/isac.c +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/isac.c @@ -251,6 +251,8 @@ int16_t WebRtcIsac_Assign(ISACStruct** ISAC_main_inst, instISAC->decoderSamplingRateKHz = kIsacWideband; instISAC->bandwidthKHz = isac8kHz; instISAC->in_sample_rate_hz = 16000; + + WebRtcIsac_InitTransform(&instISAC->transform_tables); return 0; } else { return -1; @@ -284,6 +286,8 @@ int16_t WebRtcIsac_Create(ISACStruct** ISAC_main_inst) { instISAC->encoderSamplingRateKHz = kIsacWideband; instISAC->decoderSamplingRateKHz = kIsacWideband; instISAC->in_sample_rate_hz = 16000; + + WebRtcIsac_InitTransform(&instISAC->transform_tables); return 0; } else { return -1; @@ -579,7 +583,8 @@ int WebRtcIsac_Encode(ISACStruct* ISAC_main_inst, GetSendBandwidthInfo(instISAC, &bottleneckIdx, &jitterInfo); /* Encode lower-band. */ - streamLenLB = WebRtcIsac_EncodeLb(inFrame, &instLB->ISACencLB_obj, + streamLenLB = WebRtcIsac_EncodeLb(&instISAC->transform_tables, + inFrame, &instLB->ISACencLB_obj, instISAC->codingMode, bottleneckIdx); if (streamLenLB < 0) { return -1; @@ -606,12 +611,14 @@ int WebRtcIsac_Encode(ISACStruct* ISAC_main_inst, /* Encode upper-band. */ switch (instISAC->bandwidthKHz) { case isac12kHz: { - streamLenUB = WebRtcIsac_EncodeUb12(inFrame, &instUB->ISACencUB_obj, + streamLenUB = WebRtcIsac_EncodeUb12(&instISAC->transform_tables, + inFrame, &instUB->ISACencUB_obj, jitterInfo); break; } case isac16kHz: { - streamLenUB = WebRtcIsac_EncodeUb16(inFrame, &instUB->ISACencUB_obj, + streamLenUB = WebRtcIsac_EncodeUb16(&instISAC->transform_tables, + inFrame, &instUB->ISACencUB_obj, jitterInfo); break; } @@ -1106,7 +1113,8 @@ static int Decode(ISACStruct* ISAC_main_inst, /* Regardless of that the current codec is setup to work in * wideband or super-wideband, the decoding of the lower-band * has to be performed. */ - numDecodedBytesLB = WebRtcIsac_DecodeLb(outFrame, decInstLB, + numDecodedBytesLB = WebRtcIsac_DecodeLb(&instISAC->transform_tables, + outFrame, decInstLB, &numSamplesLB, isRCUPayload); if ((numDecodedBytesLB < 0) || (numDecodedBytesLB > lenEncodedLBBytes) || @@ -1249,8 +1257,8 @@ static int Decode(ISACStruct* ISAC_main_inst, switch (bandwidthKHz) { case isac12kHz: { - numDecodedBytesUB = WebRtcIsac_DecodeUb12(outFrame, decInstUB, - isRCUPayload); + numDecodedBytesUB = WebRtcIsac_DecodeUb12( + &instISAC->transform_tables, outFrame, decInstUB, isRCUPayload); /* Hang-over for transient alleviation - * wait two frames to add the upper band going up from 8 kHz. */ @@ -1277,8 +1285,8 @@ static int Decode(ISACStruct* ISAC_main_inst, break; } case isac16kHz: { - numDecodedBytesUB = WebRtcIsac_DecodeUb16(outFrame, decInstUB, - isRCUPayload); + numDecodedBytesUB = WebRtcIsac_DecodeUb16( + &instISAC->transform_tables, outFrame, decInstUB, isRCUPayload); break; } default: diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/structs.h b/webrtc/modules/audio_coding/codecs/isac/main/source/structs.h index eb85cf34d..c4062d753 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/structs.h +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/structs.h @@ -428,6 +428,16 @@ typedef struct { uint8_t stream[3]; } transcode_obj; +typedef struct { + // TODO(kwiberg): The size of these tables could be reduced by storing floats + // instead of doubles, and by making use of the identity cos(x) = + // sin(x+pi/2). They could also be made global constants that we fill in at + // compile time. + double costab1[FRAMESAMPLES_HALF]; + double sintab1[FRAMESAMPLES_HALF]; + double costab2[FRAMESAMPLES_QUARTER]; + double sintab2[FRAMESAMPLES_QUARTER]; +} TransformTables; typedef struct { // lower-band codec instance @@ -477,6 +487,9 @@ typedef struct { uint16_t in_sample_rate_hz; /* State for the input-resampler. It is only used for 48 kHz input signals. */ int16_t state_in_resampler[SIZE_RESAMPLER_STATE]; + + // Trig tables for WebRtcIsac_Time2Spec and WebRtcIsac_Spec2time. + TransformTables transform_tables; } ISACMainStruct; #endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_ */ diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/transform.c b/webrtc/modules/audio_coding/codecs/isac/main/source/transform.c index ea6b57909..8992897f4 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/transform.c +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/transform.c @@ -14,41 +14,33 @@ #include "os_specific_inline.h" #include -static double costab1[FRAMESAMPLES_HALF]; -static double sintab1[FRAMESAMPLES_HALF]; -static double costab2[FRAMESAMPLES_QUARTER]; -static double sintab2[FRAMESAMPLES_QUARTER]; - -void WebRtcIsac_InitTransform() -{ +void WebRtcIsac_InitTransform(TransformTables* tables) { int k; double fact, phase; fact = PI / (FRAMESAMPLES_HALF); phase = 0.0; for (k = 0; k < FRAMESAMPLES_HALF; k++) { - costab1[k] = cos(phase); - sintab1[k] = sin(phase); + tables->costab1[k] = cos(phase); + tables->sintab1[k] = sin(phase); phase += fact; } fact = PI * ((double) (FRAMESAMPLES_HALF - 1)) / ((double) FRAMESAMPLES_HALF); phase = 0.5 * fact; for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { - costab2[k] = cos(phase); - sintab2[k] = sin(phase); + tables->costab2[k] = cos(phase); + tables->sintab2[k] = sin(phase); phase += fact; } } - -void WebRtcIsac_Time2Spec(double *inre1, - double *inre2, - int16_t *outreQ7, - int16_t *outimQ7, - FFTstr *fftstr_obj) -{ - +void WebRtcIsac_Time2Spec(const TransformTables* tables, + double* inre1, + double* inre2, + int16_t* outreQ7, + int16_t* outimQ7, + FFTstr* fftstr_obj) { int k; int dims[1]; double tmp1r, tmp1i, xr, xi, yr, yi, fact; @@ -61,8 +53,8 @@ void WebRtcIsac_Time2Spec(double *inre1, /* Multiply with complex exponentials and combine into one complex vector */ fact = 0.5 / sqrt(FRAMESAMPLES_HALF); for (k = 0; k < FRAMESAMPLES_HALF; k++) { - tmp1r = costab1[k]; - tmp1i = sintab1[k]; + tmp1r = tables->costab1[k]; + tmp1i = tables->sintab1[k]; tmpre[k] = (inre1[k] * tmp1r + inre2[k] * tmp1i) * fact; tmpim[k] = (inre2[k] * tmp1r - inre1[k] * tmp1i) * fact; } @@ -78,8 +70,8 @@ void WebRtcIsac_Time2Spec(double *inre1, xi = tmpim[k] - tmpim[FRAMESAMPLES_HALF - 1 - k]; yr = tmpim[k] + tmpim[FRAMESAMPLES_HALF - 1 - k]; - tmp1r = costab2[k]; - tmp1i = sintab2[k]; + tmp1r = tables->costab2[k]; + tmp1i = tables->sintab2[k]; outreQ7[k] = (int16_t)WebRtcIsac_lrint((xr * tmp1r - xi * tmp1i) * 128.0); outimQ7[k] = (int16_t)WebRtcIsac_lrint((xr * tmp1i + xi * tmp1r) * 128.0); outreQ7[FRAMESAMPLES_HALF - 1 - k] = (int16_t)WebRtcIsac_lrint((-yr * tmp1i - yi * tmp1r) * 128.0); @@ -87,10 +79,12 @@ void WebRtcIsac_Time2Spec(double *inre1, } } - -void WebRtcIsac_Spec2time(double *inre, double *inim, double *outre1, double *outre2, FFTstr *fftstr_obj) -{ - +void WebRtcIsac_Spec2time(const TransformTables* tables, + double* inre, + double* inim, + double* outre1, + double* outre2, + FFTstr* fftstr_obj) { int k; double tmp1r, tmp1i, xr, xi, yr, yi, fact; @@ -100,8 +94,8 @@ void WebRtcIsac_Spec2time(double *inre, double *inim, double *outre1, double *ou for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { /* Move zero in time to beginning of frames */ - tmp1r = costab2[k]; - tmp1i = sintab2[k]; + tmp1r = tables->costab2[k]; + tmp1i = tables->sintab2[k]; xr = inre[k] * tmp1r + inim[k] * tmp1i; xi = inim[k] * tmp1r - inre[k] * tmp1i; yr = -inim[FRAMESAMPLES_HALF - 1 - k] * tmp1r - inre[FRAMESAMPLES_HALF - 1 - k] * tmp1i; @@ -122,8 +116,8 @@ void WebRtcIsac_Spec2time(double *inre, double *inim, double *outre1, double *ou /* Demodulate and separate */ fact = sqrt(FRAMESAMPLES_HALF); for (k = 0; k < FRAMESAMPLES_HALF; k++) { - tmp1r = costab1[k]; - tmp1i = sintab1[k]; + tmp1r = tables->costab1[k]; + tmp1i = tables->sintab1[k]; xr = (outre1[k] * tmp1r - outre2[k] * tmp1i) * fact; outre2[k] = (outre2[k] * tmp1r + outre1[k] * tmp1i) * fact; outre1[k] = xr;